home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / tde40.zip / utils.c < prev    next >
C/C++ Source or Header  |  1994-06-05  |  84KB  |  2,939 lines

  1. /*******************  start of original comments  ********************/
  2. /*
  3.  * Written by Douglas Thomson (1989/1990)
  4.  *
  5.  * This source code is released into the public domain.
  6.  */
  7.  
  8. /*
  9.  * Name:    dte - Doug's Text Editor program - miscellaneous utilities
  10.  * Purpose: This file contains miscellaneous functions that were required
  11.  *           in more than one of the other files, or were thought to be
  12.  *           likely to be used elsewhere in the future.
  13.  * File:    utils.c
  14.  * Author:  Douglas Thomson
  15.  * System:  this file is intended to be system-independent
  16.  * Date:    October 1, 1989
  17.  */
  18. /*********************  end of original comments  ********************/
  19.  
  20.  
  21. /*
  22.  * The utility routines have been EXTENSIVELY rewritten.  Update screens as
  23.  * needed.  Most times, only one line has changed.  Just show changed line
  24.  * in all windows if it is on screen.
  25.  *
  26.  * Support routines for text lines longer than screen width have been added.
  27.  * Currently support lines as long as 1040 characters.
  28.  *
  29.  * In DTE, Doug chose to test whether characters are part of a word.  In TDE,
  30.  * we will test whether characters are not part of a word.  The character
  31.  * set not part of a word will not change as much as the characters that
  32.  * are part of a word.  In most languages, human and computer, the delimiters
  33.  * are much more common across languages than the tokens that make up a word.
  34.  * Thanks to Pierre Jelenc, pcj1@columbia.edu, for recommending looking for
  35.  * delimiters.
  36.  *
  37.  * New editor name:  TDE, the Thomson-Davis Editor.
  38.  * Author:           Frank Davis
  39.  * Date:             June 5, 1991, version 1.0
  40.  * Date:             July 29, 1991, version 1.1
  41.  * Date:             October 5, 1991, version 1.2
  42.  * Date:             January 20, 1992, version 1.3
  43.  * Date:             February 17, 1992, version 1.4
  44.  * Date:             April 1, 1992, version 1.5
  45.  * Date:             June 5, 1992, version 2.0
  46.  * Date:             October 31, 1992, version 2.1
  47.  * Date:             April 1, 1993, version 2.2
  48.  * Date:             June 5, 1993, version 3.0
  49.  * Date:             August 29, 1993, version 3.1
  50.  * Date:             November 13, 1993, version 3.2
  51.  * Date:             June 5, 1994, version 4.0
  52.  *
  53.  * This modification of Douglas Thomson's code is released into the
  54.  * public domain, Frank Davis.  You may distribute it freely.
  55.  */
  56.  
  57. #include "tdestr.h"
  58. #include "common.h"
  59. #include "define.h"
  60. #include "tdefunc.h"
  61.  
  62.  
  63. /*
  64.  * Name:    myiswhitespc
  65.  * Purpose: To determine whether or not a character is *NOT* part of a "word".
  66.  * Date:    July 4, 1992
  67.  * Passed:  c: the character to be tested
  68.  * Returns: TRUE if c is in the character set *NOT* part of a word
  69.  * Notes:   The characters in the set not part of a word will not change as
  70.  *           as much as the characters that are part of a word.  In most
  71.  *           languages, human and computer, the delimiters are much more
  72.  *           common than the tokens that make up a word.  For example,
  73.  *           the set of punction characters don't change as much across
  74.  *           languages, human and computer, as the characters that make
  75.  *           up the alphabet, usually.  In other words, the delimiters
  76.  *           are fairly constant across languages.
  77.  */
  78. int  myiswhitespc( int c )
  79. {
  80.    return( c == ' ' || (bj_ispunct( c ) && c != '_') || bj_iscntrl( c ) );
  81. }
  82.  
  83.  
  84. /*
  85.  * Name:    check_virtual_col
  86.  * Purpose: ensure integrity of rcol, ccol, and bcol
  87.  * Date:    June 5, 1991
  88.  * Passed:  window:  pointer to current window
  89.  *          rcol: real column of cursor
  90.  *          ccol: current or logical column of cursor
  91.  */
  92. void check_virtual_col( TDE_WIN *window, int rcol, int ccol )
  93. {
  94. register int bcol;
  95. int  start_col;
  96. int  end_col;
  97. file_infos *file;
  98.  
  99.    file      = window->file_info;
  100.    bcol      = window->bcol;
  101.    start_col = window->start_col;
  102.    end_col   = window->end_col;
  103.  
  104.    /*
  105.     * is logical column past end of screen?
  106.     */
  107.    if (ccol > end_col) {
  108. /*      ccol = start_col + (end_col + 1 - start_col) / 2;  */
  109.       ccol = rcol - bcol + start_col;
  110.       if (ccol > end_col) {
  111.          ccol = end_col;
  112.          bcol = rcol - (ccol - start_col);
  113.          file->dirty = LOCAL;
  114. /*
  115.  *        ccol = start_col + (end_col + 1 - start_col) / 2;
  116.  *        bcol = rcol - ccol + start_col;
  117.  *        file->dirty = LOCAL;
  118.  */
  119.       }
  120.    }
  121.  
  122.    /*
  123.     * is logical column behind start of screen?
  124.     */
  125.    if (ccol < start_col) {
  126.       if (bcol >= (start_col - ccol))
  127.          bcol -= (start_col - ccol);
  128.       ccol = start_col;
  129.       file->dirty = LOCAL;
  130.    }
  131.  
  132.    /*
  133.     * is real column < base column?
  134.     */
  135.    if (rcol < bcol) {
  136.       ccol = rcol + start_col;
  137.       bcol = 0;
  138.       if (ccol > end_col) {
  139.          bcol = rcol;
  140.          ccol = start_col;
  141.       }
  142.       file->dirty = LOCAL;
  143.    }
  144.  
  145.    /*
  146.     * current column + base column MUST equal real column
  147.     */
  148.    if ((ccol - start_col) + bcol != rcol) {
  149.       if (bcol < 0 || bcol > rcol) {
  150.          bcol = rcol;
  151.          file->dirty = LOCAL;
  152.       }
  153.       ccol = rcol - bcol + start_col;
  154.       if (ccol > end_col) {
  155.          bcol = rcol;
  156.          ccol = start_col;
  157.          file->dirty = LOCAL;
  158.       }
  159.    }
  160.  
  161.    /*
  162.     * rcol CANNOT be negative
  163.     */
  164.    if (rcol < 0) {
  165.       rcol = bcol = 0;
  166.       ccol = start_col;
  167.       file->dirty = LOCAL;
  168.    }
  169.  
  170.    if (rcol >= MAX_LINE_LENGTH) {
  171.       rcol = MAX_LINE_LENGTH - 1;
  172.       bcol = rcol - (ccol - start_col);
  173.    }
  174.  
  175.    assert( rcol >= 0 );
  176.    assert( rcol < MAX_LINE_LENGTH );
  177.    assert( bcol >= 0 );
  178.    assert( bcol < MAX_LINE_LENGTH );
  179.    assert( ccol >= start_col );
  180.    assert( ccol <= end_col );
  181.  
  182.    window->bcol = bcol;
  183.    window->ccol = ccol;
  184.    window->rcol = rcol;
  185. }
  186.  
  187.  
  188. /*
  189.  * Name:    copy_line
  190.  * Purpose: To copy the cursor line, if necessary, into the current line
  191.  *           buffer, so that changes can be made efficiently.
  192.  * Date:    June 5, 1991
  193.  * Passed:  text_line: line to be copied to line buffer
  194.  *          line: line to display error message
  195.  * Notes:   See un_copy_line, the reverse operation.
  196.  *          DO NOT use the C library string functions on text in
  197.  *           g_status.line_buff, because Null characters are allowed as
  198.  *           normal text in the file.
  199.  */
  200. void copy_line( line_list_ptr ll )
  201. {
  202. register unsigned int len;
  203. text_ptr text_line;
  204.  
  205.    if (g_status.copied == FALSE  &&  ll->len != EOF) {
  206.  
  207.       assert( ll != NULL );
  208.  
  209.       len = ll->len;
  210.       text_line = ll->line;
  211.       g_status.buff_node = ll;
  212.  
  213.       assert( len < MAX_LINE_LENGTH );
  214.  
  215.       if (text_line != NULL)
  216.          my_memcpy( g_status.line_buff, text_line, len );
  217.  
  218.       g_status.line_buff_len = len;
  219.       g_status.copied = TRUE;
  220.    }
  221. }
  222.  
  223.  
  224. /*
  225.  * Name:    un_copy_line
  226.  * Purpose: To copy the cursor line, if necessary, from the current line
  227.  *           buffer, shifting the main text to make the right amount of
  228.  *           room.
  229.  * Date:    June 5, 1991
  230.  * Passed:  test_line:  location in file to copy line buffer
  231.  *          window:  pointer to current window
  232.  *          del_trailing:  delete the trailing blanks at eol? TRUE or FALSE
  233.  * Notes:   For some functions, trailing spaces should not be removed when
  234.  *           returning the line buffer to the main text.  The JoinLine function
  235.  *           is a good example.  We need to leave trailing space so when we
  236.  *           join lines - the current line will extend at least up to
  237.  *           the column of the cursor.  We need to leave trailing space
  238.  *           during BOX block operations.
  239.  *          See copy_line, the reverse operation.
  240.  */
  241. int  un_copy_line( line_list_ptr ll, TDE_WIN *window, int del_trailing )
  242. {
  243. text_ptr p;
  244. size_t len;     /* length of line buffer text */
  245. size_t ll_len;  /* length of ll->line */
  246. int  net_change;
  247. int  rc;
  248. char c;
  249. file_infos *file;
  250. TDE_WIN *wp;
  251.  
  252.    rc = OK;
  253.    if (mode.do_backups == TRUE)
  254.       rc = backup_file( window );
  255.  
  256.    if (g_status.copied == TRUE  &&  ll->len != EOF) {
  257.  
  258.       file = window->file_info;
  259.  
  260.       /*
  261.        * if we are deleting the entire line, don't worry about the
  262.        *  deleting the trailing space, since we're deleting entire line.
  263.        */
  264.       if (g_status.command == DeleteLine)
  265.          del_trailing = FALSE;
  266.  
  267.       if (del_trailing  &&  mode.trailing  &&  file->crlf != BINARY) {
  268.          len = g_status.line_buff_len;
  269.          for (p=(text_ptr)(g_status.line_buff+len); len > 0; len--, p--) {
  270.             c = *(p - 1);
  271.             if (c != ' '  &&  c != '\t')
  272.                break;
  273.             if (!mode.inflate_tabs && c == '\t')
  274.                break;
  275.          }
  276.          g_status.line_buff_len = len;
  277.          file->dirty = GLOBAL;
  278.          if (window->visible == TRUE)
  279.             show_changed_line( window );
  280.       }
  281.       len = g_status.line_buff_len;
  282.       ll_len =  (ll->line == NULL) ? 0 : ll->len;
  283.  
  284.  
  285.       assert( len < MAX_LINE_LENGTH );
  286.       assert( ll_len < MAX_LINE_LENGTH );
  287.  
  288.       net_change = len - ll_len;
  289.  
  290.       if (ll_len != len  ||  ll->line == NULL) {
  291.          /*
  292.           * let malloc space for the new line before we free the old line.
  293.           */
  294.          p = my_malloc( len, &rc );
  295.          if (rc == ERROR)
  296.             error( WARNING, window->bottom_line, main4 );
  297.  
  298.          /*
  299.           * free the space taken up by current line in FAR heap.
  300.           */
  301.          if (rc != ERROR  &&  ll->line != NULL)
  302.             my_free( ll->line );
  303.       } else
  304.          p = ll->line;
  305.  
  306.       if (rc != ERROR) {
  307.          if (len > 0)
  308.             my_memcpy( p, g_status.line_buff, len );
  309.          ll->line = p;
  310.          ll->len = len;
  311.  
  312.          if (net_change != 0) {
  313.             for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  314.                if (wp->file_info == file && wp != window)
  315.                   if (wp->rline > window->rline)
  316.                      wp->bin_offset += net_change;
  317.             }
  318.          }
  319.  
  320.          file->modified = TRUE;
  321.          show_avail_mem( );
  322.       }
  323.    }
  324.    g_status.copied = FALSE;
  325.    return( rc );
  326. }
  327.  
  328.  
  329. /*
  330.  * Name:    un_copy_tab_buffer
  331.  * Purpose: To copy the tab buffer line the main text buffer
  332.  * Date:    October 31, 1992
  333.  * Passed:  line_number:  line number to copy line tab out buffer
  334.  *          window:       pointer to current window
  335.  */
  336. int  un_copy_tab_buffer( line_list_ptr ll, TDE_WIN *window )
  337. {
  338. text_ptr p;
  339. int  len;               /* length of current line buffer text */
  340. int  net_change;
  341. int  rc;
  342. file_infos *file;
  343. TDE_WIN *wp;
  344.  
  345.    rc = OK;
  346.    file = window->file_info;
  347.    /*
  348.     * file has changed.  lets create the back_up if needed
  349.     */
  350.    if (mode.do_backups == TRUE) {
  351.       window->file_info->modified = TRUE;
  352.       rc = backup_file( window );
  353.    }
  354.  
  355.    len = g_status.tabout_buff_len;
  356.  
  357.    assert( len >= 0 );
  358.    assert( len < MAX_LINE_LENGTH );
  359.    assert( ll->len >= 0 );
  360.    assert( ll->len < MAX_LINE_LENGTH );
  361.  
  362.    /*
  363.     * if the FAR heap has run out of space, then only part of the
  364.     *  current line can be moved back into the FAR heap. Warn the user
  365.     *  that some of the current line has been lost.
  366.     */
  367.    p = my_malloc( len, &rc );
  368.    if (rc == ERROR)
  369.       error( WARNING, window->bottom_line, main4 );
  370.  
  371.    if (rc == OK) {
  372.       net_change = len - ll->len;
  373.  
  374.       if (ll->line != NULL)
  375.          my_free( ll->line );
  376.       if (len > 0)
  377.          my_memcpy( p, g_status.line_buff, len );
  378.       ll->line = p;
  379.       ll->len  = len;
  380.  
  381.       if (net_change != 0) {
  382.          for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  383.             if (wp->file_info == file && wp != window)
  384.                if (wp->rline > window->rline)
  385.                   wp->bin_offset += net_change;
  386.          }
  387.       }
  388.  
  389.       file->modified = TRUE;
  390.    }
  391.    return( rc );
  392. }
  393.  
  394.  
  395. /*
  396.  * Name:    load_undo_buffer
  397.  * Purpose: To copy the cursor line to the undo buffer.
  398.  * Date:    September 26, 1991
  399.  * Passed:  file:          pointer to file
  400.  *          line_to_undo:  pointer to line in file to save
  401.  * Notes:   save the last mode.undo_max lines in a stack.  when we overflow
  402.  *           the stack, dump the oldest line.
  403.  */
  404. void load_undo_buffer( file_infos *file, text_ptr line_to_undo, int len )
  405. {
  406. int  rc;
  407. text_ptr l;
  408. line_list_ptr temp_ll;
  409.  
  410.    rc = OK;
  411.    if (file->undo_count >= mode.undo_max) {
  412.       --file->undo_count;
  413.       temp_ll = file->undo_bot->prev;
  414.       temp_ll->prev->next = file->undo_bot;
  415.       file->undo_bot->prev = temp_ll->prev;
  416.       if (temp_ll->line != NULL)
  417.          my_free( temp_ll->line );
  418.    } else
  419.       temp_ll = (line_list_ptr)my_malloc( sizeof(line_list_struc), &rc );
  420.  
  421.    assert( len >= 0 );
  422.    assert( len < MAX_LINE_LENGTH );
  423.  
  424.    l = my_malloc( len, &rc );
  425.  
  426.    if (rc == ERROR) {
  427.       if (l != NULL)
  428.          my_free( l );
  429.       if (temp_ll != NULL)
  430.          my_free( temp_ll );
  431.    } else {
  432.       if (len > 0)
  433.          my_memcpy( l, line_to_undo, len );
  434.       temp_ll->line  = l;
  435.       temp_ll->len   = len;
  436.       temp_ll->dirty = TRUE;
  437.  
  438.       temp_ll->prev = NULL;
  439.       temp_ll->next = file->undo_top;
  440.       file->undo_top->prev = temp_ll;
  441.       file->undo_top = temp_ll;
  442.  
  443.       ++file->undo_count;
  444.    }
  445. }
  446.  
  447.  
  448. /*
  449.  * Name:    set_prompt
  450.  * Purpose: To display a prompt, highlighted, at the bottom of the screen.
  451.  * Date:    October 1, 1989
  452.  * Passed:  prompt: prompt to be displayed
  453.  *          line:   line to display prompt
  454.  */
  455. void set_prompt( char *prompt, int line )
  456. {
  457. register int prompt_col;
  458.  
  459.    /*
  460.     * work out where the answer should go
  461.     */
  462.    prompt_col = strlen( prompt );
  463.  
  464.    assert( prompt_col <= g_display.ncols );
  465.  
  466.    /*
  467.     * output the prompt
  468.     */
  469.    s_output( prompt, line, 0, g_display.message_color );
  470.    eol_clear( prompt_col, line, g_display.message_color );
  471.  
  472.    /*
  473.     * put cursor at end of prompt
  474.     */
  475.    xygoto( prompt_col, line );
  476. }
  477.  
  478.  
  479. /*
  480.  * Name:    get_name
  481.  * Purpose: To prompt the user and read the string entered in response.
  482.  * Date:    June 5, 1992
  483.  * Passed:  prompt: prompt to offer the user
  484.  *          line:   line to display prompt
  485.  *          name:   default answer
  486.  *          color:  color to display prompt
  487.  * Returns: name:   user's answer
  488.  *          OK if user entered something
  489.  *          ERROR if user aborted the command
  490.  * Notes:   with the addition of macros in tde, this function became a little
  491.  *           more complicated.  we have to deal with both executing macros
  492.  *           and macros that are the user uses when entering normal text
  493.  *           at the prompt.  i call these local and global macros.  a global
  494.  *           macro is when this function is called from a running macro.
  495.  *           the running macro can enter text and return from this function
  496.  *           w/o any action from the user.  a local macro is when the user
  497.  *           presses a key inside this function, which happens quite often
  498.  *           when keys are assigned to ASCII and Extended ASCII characters.
  499.  */
  500. int  get_name( char *prompt, int line, char *name, int color )
  501. {
  502. int  col;               /* cursor column for answer */
  503. int  c;                 /* character user just typed */
  504. char *cp;               /* cursor position in answer */
  505. char *answer;           /* user's answer */
  506. int first = TRUE;       /* first character typed */
  507. register int len;       /* length of answer */
  508. int  plen;              /* length of prompt */
  509. int  func;              /* function of key pressed */
  510. int  stop;              /* flag to stop getting characters */
  511. char *p;                /* for copying text in answer */
  512. char buffer[MAX_COLS+2];/* line on which name is being entered */
  513. int  normal;
  514. int  local_macro = FALSE;
  515. int  next;
  516. int  regx_help_on;
  517. char **pp;
  518. int  i;
  519. #if defined( __UNIX__ )
  520.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  521. #else
  522.  char display_buff[(MAX_COLS+2)*2];
  523. #endif
  524.  
  525.    /*
  526.     * set up prompt and default
  527.     */
  528.    assert( strlen( prompt ) < (size_t)g_display.ncols );
  529.    assert( strlen( name )   < (size_t)g_display.ncols );
  530.  
  531.    strcpy( buffer, prompt );
  532.    plen = strlen( prompt );
  533.    answer = buffer + plen;
  534.    strcpy( answer, name );
  535.  
  536.    /*
  537.     * let user edit default string
  538.     */
  539.    next = regx_help_on = FALSE;
  540.    len = strlen( answer );
  541.    col = strlen( buffer );
  542.    g_status.prompt_line = line;
  543.    g_status.prompt_col = col;
  544.    cp = answer + len;
  545.    normal = g_display.text_color;
  546.    save_screen_line( 0, line, display_buff );
  547.    s_output( buffer, line, 0, color );
  548.    eol_clear( col, line, normal );
  549.    for (stop = FALSE; stop == FALSE;) {
  550.       if (regx_help_on == TRUE)
  551.          xygoto( -1, -1 );
  552.       else
  553.          xygoto( col, line );
  554.       if (g_status.macro_executing) {
  555.          next = g_status.macro_next;
  556.          g_status.macro_next = macro.strokes[g_status.macro_next].next;
  557.          if (g_status.macro_next != -1) {
  558.             c = macro.strokes[g_status.macro_next].key;
  559.             func = getfunc( c );
  560.             if (func == PlayBack) {
  561.                stop = TRUE;
  562.                g_status.macro_next = next;
  563.             }
  564.          } else {
  565.             c = 0x100;
  566.             func = AbortCommand;
  567.             stop = TRUE;
  568.          }
  569.       } else {
  570.          if (local_macro == FALSE) {
  571.             c = getkey( );
  572.             func = getfunc( c );
  573.  
  574.             /*
  575.              * User may have redefined the Enter and ESC keys.  Make the Enter
  576.              *  key perform a Rturn in this function. Make the ESC key do an
  577.              *  AbortCommand.
  578.              */
  579.             if (c == RTURN)
  580.                func = Rturn;
  581.             else if (c == ESC)
  582.                func = AbortCommand;
  583.  
  584.             if (func == PlayBack) {
  585.                local_macro = TRUE;
  586.                next = macro.first_stroke[ c-256 ];
  587.                c = macro.strokes[next].key;
  588.                func = getfunc( c );
  589.                next = macro.strokes[next].next;
  590.             } else {
  591.                g_status.key_pressed = c;
  592.                record_keys( line );
  593.             }
  594.          } else {
  595.             if (next != -1) {
  596.                c = macro.strokes[next].key;
  597.                next = macro.strokes[next].next;
  598.             } else {
  599.                local_macro = FALSE;
  600.                c = 0x100;
  601.             }
  602.             func = getfunc( c );
  603.          }
  604.       }
  605.       if (c == _F1)
  606.          func = Help;
  607.       if (regx_help_on == TRUE  &&  g_status.current_window != NULL) {
  608.          redraw_screen( g_status.current_window );
  609.          s_output( buffer, line, 0, color );
  610.          eol_clear( col, line, normal );
  611.          s_output( cp, line, col, color );
  612.          regx_help_on = FALSE;
  613.       } else {
  614.          switch (func) {
  615.             case Help :
  616.                if ((g_status.command == FindRegX  ||
  617.                     g_status.command == RepeatFindRegX) &&
  618.                     regx_help_on == FALSE) {
  619.                   regx_help_on = TRUE;
  620.                   for (i=3,pp=regx_help; *pp != NULL; pp++, i++)
  621.                      s_output( *pp, i, 12, g_display.help_color );
  622.                }
  623.                break;
  624.             case ToggleSearchCase :
  625.                mode.search_case = mode.search_case == IGNORE ? MATCH : IGNORE;
  626.                build_boyer_array( );
  627.                show_search_case( );
  628.                break;
  629.             case Rturn       :
  630.             case NextLine    :
  631.             case BegNextLine :
  632.                answer[len] = '\0';
  633.                assert( strlen( answer ) < (size_t)g_display.ncols );
  634.                strcpy( name, answer );
  635.                /*
  636.                 * finished
  637.                 */
  638.                stop = TRUE;
  639.                break;
  640.             case BackSpace :
  641.                /*
  642.                 * delete to left of cursor
  643.                 */
  644.                if (cp > answer) {
  645.                   for (p=cp-1; p < answer+len; p++) {
  646.                      *p = *(p+1);
  647.                   }
  648.                   --len;
  649.                   --col;
  650.                   --cp;
  651.                   c_output( ' ', plen+len, line, normal );
  652.                   s_output( cp, line, col, color );
  653.                   *(answer + len) = '\0';
  654.                }
  655.                break;
  656.             case DeleteChar :
  657.                /*
  658.                 * delete char under cursor
  659.                 */
  660.                if (*cp) {
  661.                   for (p=cp; p < answer+len; p++) {
  662.                      *p = *(p+1);
  663.                   }
  664.                   --len;
  665.                   c_output( ' ', plen+len, line, normal );
  666.                   s_output( cp, line, col, color );
  667.                   *(answer + len) = '\0';
  668.                }
  669.                break;
  670.             case DeleteLine :
  671.                /*
  672.                 * delete current line
  673.                 */
  674.                col = plen;
  675.                cp = answer;
  676.                *cp = '\0';
  677.                len = 0;
  678.                eol_clear( col, line, normal );
  679.                break;
  680.             case AbortCommand :
  681.                stop = TRUE;
  682.                break;
  683.             case CharLeft :
  684.                /*
  685.                 * move cursor left
  686.                 */
  687.                if (cp > answer) {
  688.                   col--;
  689.                   cp--;
  690.                }
  691.                break;
  692.             case CharRight :
  693.                /*
  694.                 * move cursor right
  695.                 */
  696.                if (*cp) {
  697.                   col++;
  698.                   cp++;
  699.                 }
  700.                 break;
  701.             case BegOfLine :
  702.                /*
  703.                 * move cursor to start of line
  704.                 */
  705.                col = plen;
  706.                cp = answer;
  707.                break;
  708.             case EndOfLine :
  709.                /*
  710.                 * move cursor to end of line
  711.                 */
  712.                col = plen + len;
  713.                cp = answer + len;
  714.                break;
  715.             default :
  716.                if (c < 0x100) {
  717.                   /*
  718.                    * insert character at cursor
  719.                    */
  720.                   if (first) {
  721.                      /*
  722.                       * delete previous answer
  723.                       */
  724.                      col = plen;
  725.                      cp = answer;
  726.                      *cp = '\0';
  727.                      len = 0;
  728.                      eol_clear( col, line, normal );
  729.                   }
  730.  
  731.                   /*
  732.                    * insert new character
  733.                    */
  734.                   if (col < g_display.ncols-1) {
  735.                      if (*cp == '\0') {
  736.                         ++len;
  737.                         *(answer + len) = '\0';
  738.                      }
  739.                      *cp = (char)c;
  740.                      c_output( c, col, line, color );
  741.                      ++cp;
  742.                      ++col;
  743.                   }
  744.                }
  745.                break;
  746.          }
  747.       }
  748.       first = FALSE;
  749.    }
  750.    restore_screen_line( 0, line, display_buff );
  751.    return( func == AbortCommand ? ERROR : OK );
  752. }
  753.  
  754.  
  755. /*
  756.  * Name:     get_sort_order
  757.  * Purpose:  To prompt the user and get sort direction
  758.  * Date:     June 5, 1992
  759.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  760.  * Passed:   window
  761.  * Returns:  OK if user entered something
  762.  *           ERROR if user aborted the command
  763.  */
  764. int  get_sort_order( TDE_WIN *window )
  765. {
  766. register int c;
  767. int  col;
  768. #if defined( __UNIX__ )
  769.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  770. #else
  771.  char display_buff[(MAX_COLS+2)*2];
  772. #endif
  773.  
  774.    save_screen_line( 0, window->bottom_line, display_buff );
  775.    /*
  776.     * sort ascending or descending
  777.     */
  778.    s_output( utils4, window->bottom_line, 0, g_display.message_color );
  779.    c = strlen( utils4 );
  780.    eol_clear( c, window->bottom_line, g_display.text_color );
  781.    xygoto( c, window->bottom_line );
  782.    do {
  783.       c = getanswerkey( );
  784.       col = getfunc( c );
  785.       if (c == ESC)
  786.          col = AbortCommand;
  787.    } while (col != AbortCommand  &&  c != L_ASCENDING  &&  c != L_DESCENDING);
  788.    switch ( c ) {
  789.       case L_ASCENDING :
  790.          sort.direction = ASCENDING;
  791.          break;
  792.       case L_DESCENDING :
  793.          sort.direction = DESCENDING;
  794.          break;
  795.       default  :
  796.          col = AbortCommand;
  797.          break;
  798.    }
  799.    restore_screen_line( 0, window->bottom_line, display_buff );
  800.    return( col == AbortCommand ? ERROR : OK );
  801. }
  802.  
  803.  
  804. /*
  805.  * Name:     get_replace_direction
  806.  * Purpose:  To prompt the user and get replace string direction
  807.  * Date:     October 31, 1992
  808.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  809.  * Passed:   window
  810.  * Returns:  OK if user entered something
  811.  *           ERROR if user aborted the command
  812.  */
  813. int  get_replace_direction( TDE_WIN *window )
  814. {
  815. register int c;
  816. int  col;
  817. #if defined( __UNIX__ )
  818.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  819. #else
  820.  char display_buff[(MAX_COLS+2)*2];
  821. #endif
  822.  
  823.    save_screen_line( 0, window->bottom_line, display_buff );
  824.    /*
  825.     * replace forward or backward
  826.     */
  827.    s_output( utils5, window->bottom_line, 0, g_display.message_color );
  828.    c = strlen( utils5 );
  829.    eol_clear( c, window->bottom_line, g_display.text_color );
  830.    xygoto( c, window->bottom_line );
  831.    do {
  832.       c = getanswerkey( );
  833.       col = getfunc( c );
  834.       if (c == ESC)
  835.          col = AbortCommand;
  836.    } while (col != AbortCommand  &&  c != L_FORWARD  &&  c != L_BACKWARD);
  837.    switch ( c ) {
  838.       case L_FORWARD :
  839.          c = FORWARD;
  840.          break;
  841.       case L_BACKWARD :
  842.          c = BACKWARD;
  843.          break;
  844.       default  :
  845.          c = ERROR;
  846.    }
  847.    restore_screen_line( 0, window->bottom_line, display_buff );
  848.    return( col == AbortCommand ? ERROR : c );
  849. }
  850.  
  851.  
  852. /*
  853.  * Name:     get_yn
  854.  * Purpose:  To input a response of yes or no.
  855.  * Date:     October 1, 1989
  856.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  857.  * Returns:  the user's answer.  A_??? - see tdestr.h
  858.  */
  859. int  get_yn( void )
  860. {
  861. int  c;                 /* the user's response */
  862. register int rc;        /* return code */
  863.  
  864.    do {
  865.       c = getanswerkey( );
  866.       rc = getfunc( c );
  867.       if (c== ESC)
  868.          rc = AbortCommand;
  869.    } while (rc != AbortCommand  &&  c != L_YES  &&  c != L_NO);
  870.    if (rc == AbortCommand || c == ESC)
  871.       rc = ERROR;
  872.    else {
  873.       switch ( c ) {
  874.          case L_YES :
  875.             rc = A_YES;
  876.             break;
  877.          case L_NO :
  878.             rc = A_NO;
  879.             break;
  880.       }
  881.    }
  882.    return( rc );
  883. }
  884.  
  885.  
  886. /*
  887.  * Name:     get_lr
  888.  * Purpose:  To input a response of yes or no.
  889.  * Date:     June 1, 1991
  890.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  891.  * Returns:  the user's answer, LEFT or RIGHT.
  892.  */
  893. int  get_lr( void )
  894. {
  895. int  c;                 /* the user's response */
  896. register int rc;        /* return code */
  897.  
  898.    for (rc=OK; rc == OK;) {
  899.       c = getanswerkey( );
  900.       if (getfunc( c ) == AbortCommand || c == ESC)
  901.          rc = ERROR;
  902.       else {
  903.          switch ( c ) {
  904.             case L_LEFT :
  905.                rc = LEFT;
  906.                break;
  907.             case L_RIGHT :
  908.                rc = RIGHT;
  909.                break;
  910.          }
  911.       }
  912.    }
  913.    return( rc );
  914. }
  915.  
  916.  
  917. /*
  918.  * Name:     get_bc
  919.  * Purpose:  To input a response of beginning or current cursor postion
  920.  * Date:     October 31, 1992
  921.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  922.  * Returns:  the user's answer, Beginning or Current.
  923.  */
  924. int  get_bc( void )
  925. {
  926. int  c;                 /* the user's response */
  927. register int rc;        /* return code */
  928.  
  929.    for (rc=OK; rc == OK;) {
  930.       c = getanswerkey( );
  931.       if (getfunc( c ) == AbortCommand || c == ESC)
  932.          rc = ERROR;
  933.       else {
  934.          switch ( c ) {
  935.             case L_BEGINNING :
  936.                rc = BEGINNING;
  937.                break;
  938.             case L_CURRENT :
  939.             case 'c' :
  940.                rc = CURRENT;
  941.                break;
  942.          }
  943.       }
  944.    }
  945.    return( rc );
  946. }
  947.  
  948.  
  949. /*
  950.  * Name:     get_oa
  951.  * Purpose:  To input a response of overwrite or append.
  952.  * Date:     October 1, 1989
  953.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  954.  * Returns:  the user's answer.  A_??? - see tdestr.h
  955.  */
  956. int  get_oa( void )
  957. {
  958. int  c;                 /* the user's response */
  959. register int rc;        /* return code */
  960. int  func;
  961.  
  962.    rc = 0;
  963.    while (rc != AbortCommand && rc != A_OVERWRITE && rc != A_APPEND) {
  964.       c = getanswerkey( );
  965.       func = getfunc( c );
  966.       if (func == AbortCommand || c == ESC)
  967.          rc = AbortCommand;
  968.       switch ( c ) {
  969.          case L_OVERWRITE :
  970.             rc = A_OVERWRITE;
  971.             break;
  972.          case L_APPEND :
  973.             rc = A_APPEND;
  974.             break;
  975.       }
  976.    }
  977.    return( rc );
  978. }
  979.  
  980.  
  981. /*
  982.  * Name:    show_eof
  983.  * Purpose: display eof message
  984.  * Date:    September 16, 1991
  985.  * Notes:   line:  ususally, line to is display "<=== eof ===>"
  986.  */
  987. void show_eof( TDE_WIN *window )
  988. {
  989. register int color;
  990. char temp[MAX_COLS+2];
  991.  
  992.    assert( strlen( mode.eof ) < (size_t)g_display.ncols );
  993.  
  994.    strcpy( temp, mode.eof );
  995.    color = window->end_col + 1 - window->start_col;
  996.    if (strlen( temp ) > (unsigned)color)
  997.       temp[color] = '\0';
  998.    color = g_display.eof_color;
  999.    window_eol_clear( window, color );
  1000.    s_output( temp, window->cline, window->start_col, color );
  1001. }
  1002.  
  1003.  
  1004. /*
  1005.  * Name:    display_current_window
  1006.  * Purpose: display text in current window
  1007.  * Date:    June 5, 1991
  1008.  * Passed:  window:  pointer to current window
  1009.  * Notes:   use a temporary window structure, "w", to do the dirty work.
  1010.  */
  1011. void display_current_window( TDE_WIN *window )
  1012. {
  1013. int  count;     /* number of lines updated so far */
  1014. int  number;    /* number of lines visible in window */
  1015. register int i; /* register variable */
  1016. TDE_WIN w;      /* scratch window structure */
  1017. int  curl;      /* current line on screen, window->cline */
  1018. int  eof;
  1019.  
  1020.    /*
  1021.     * initialize the scratch variables
  1022.     */
  1023.    number = window->bottom_line - ((window->top_line + window->ruler) - 1);
  1024.    count  = window->cline - (window->top_line + window->ruler);
  1025.    dup_window_info( &w, window );
  1026.  
  1027.    w.cline -= count;
  1028.    w.rline -= count;
  1029.    for (eof=count; eof > 0; eof--)
  1030.       w.ll = w.ll->prev;
  1031.  
  1032.  
  1033.    /*
  1034.     * start at the top of the window and display a window full of text
  1035.     */
  1036.    eof = FALSE;
  1037.    curl = window->cline;
  1038.    for (i=number; i>0; i--) {
  1039.       if (w.ll->len != EOF) {
  1040.          /*
  1041.           * if this is window->cline, do not show the line because we
  1042.           *  show the curl at the end of this function.  don't show it twice
  1043.           */
  1044.          if (w.cline != curl)
  1045.             update_line( &w );
  1046.          w.ll = w.ll->next;
  1047.       } else if (eof == FALSE) {
  1048.          show_eof( &w );
  1049.          eof = TRUE;
  1050.       } else
  1051.          window_eol_clear( &w, COLOR_TEXT );
  1052.       ++w.cline;
  1053.       ++w.rline;
  1054.    }
  1055.    show_asterisk( window );
  1056.    show_curl_line( window );
  1057. }
  1058.  
  1059.  
  1060. /*
  1061.  * Name:    redraw_screen
  1062.  * Purpose: display all visible windows, modes, and headers
  1063.  * Date:    June 5, 1991
  1064.  * Passed:  window:  pointer to current window
  1065.  */
  1066. int  redraw_screen( TDE_WIN *window )
  1067. {
  1068. register TDE_WIN *above;        /* window above current */
  1069. register TDE_WIN *below;        /* window below current */
  1070.  
  1071. #if defined( __UNIX__ )
  1072.    touchwin( curscr );
  1073. #endif
  1074.  
  1075.    cls( );
  1076.  
  1077.    /*
  1078.     * display the current window
  1079.     */
  1080.    redraw_current_window( window );
  1081.  
  1082.    /*
  1083.     * now update all the other windows
  1084.     */
  1085.    above = below = window;
  1086.    while (above->prev || below->next) {
  1087.       if (above->prev) {
  1088.          above = above->prev;
  1089.          redraw_current_window( above );
  1090.       }
  1091.       if (below->next) {
  1092.          below = below->next;
  1093.          redraw_current_window( below );
  1094.       }
  1095.    }
  1096.    window->file_info->dirty = FALSE;
  1097.    show_modes( );
  1098.  
  1099. #if defined( __UNIX__ )
  1100.    refresh( );
  1101. #endif
  1102.  
  1103.    return( OK );
  1104. }
  1105.  
  1106.  
  1107. /*
  1108.  * Name:    redraw_current_window
  1109.  * Purpose: redraw all info in window
  1110.  * Date:    July 13, 1991
  1111.  * Passed:  window:  pointer to current window
  1112.  */
  1113. void redraw_current_window( TDE_WIN *window )
  1114. {
  1115.  
  1116.    /*
  1117.     * display the current window
  1118.     */
  1119.    if (window->visible) {
  1120.       display_current_window( window );
  1121.       show_window_header( window );
  1122.       show_ruler( window );
  1123.       show_ruler_pointer( window );
  1124.       if (window->vertical)
  1125.          show_vertical_separator( window );
  1126.    }
  1127. }
  1128.  
  1129.  
  1130. /*
  1131.  * Name:    show_changed_line
  1132.  * Purpose: Only one line was changed in file, just show it
  1133.  * Date:    June 5, 1991
  1134.  * Passed:  window:  pointer to current window
  1135.  */
  1136. void show_changed_line( TDE_WIN *window )
  1137. {
  1138. TDE_WIN *above;                 /* window above current */
  1139. TDE_WIN *below;                 /* window below current */
  1140. TDE_WIN w;                      /* scratch window structure */
  1141. long changed_line;              /* line number in file that was changed */
  1142. long top_line, bottom_line;     /* top and bottom line in file on screen */
  1143. int  line_on_screen;            /* is changed line on screen? */
  1144. file_infos *file;               /* file pointer */
  1145.  
  1146.    file = window->file_info;
  1147.    if ((file->dirty == LOCAL || file->dirty == GLOBAL) && window->visible)
  1148.       show_curl_line( window );
  1149.    changed_line = window->rline;
  1150.  
  1151.    /*
  1152.     * now update the line in all other windows
  1153.     */
  1154.    if (file->dirty != LOCAL) {
  1155.       above = below = window;
  1156.       while (above->prev || below->next) {
  1157.          if (above->prev) {
  1158.             above = above->prev;
  1159.             dup_window_info( &w, above );
  1160.          } else if (below->next) {
  1161.             below = below->next;
  1162.             dup_window_info( &w, below );
  1163.          }
  1164.  
  1165.          /*
  1166.           * is this window the changed file and is it visible?
  1167.           */
  1168.          if (w.file_info == file && w.visible) {
  1169.  
  1170.             /*
  1171.              * calculate file lines at top and bottom of screen.
  1172.              * the changed line may not be the curl in other windows.
  1173.              */
  1174.             line_on_screen = FALSE;
  1175.             top_line = w.rline - (w.cline - (w.top_line + w.ruler));
  1176.             bottom_line = w.rline + (w.bottom_line - w.cline);
  1177.             if (changed_line == w.rline)
  1178.                line_on_screen = CURLINE;
  1179.             else if (changed_line < w.rline && changed_line >= top_line) {
  1180.                line_on_screen = NOTCURLINE;
  1181.                while (w.rline > changed_line) {
  1182.                   w.ll = w.ll->prev;
  1183.                   --w.rline;
  1184.                   --w.cline;
  1185.                }
  1186.             } else if (changed_line > w.rline && changed_line <= bottom_line) {
  1187.                line_on_screen = NOTCURLINE;
  1188.                while (w.rline < changed_line) {
  1189.                   w.ll = w.ll->next;
  1190.                   ++w.rline;
  1191.                   ++w.cline;
  1192.                }
  1193.             }
  1194.  
  1195.             /*
  1196.              * display the changed line if on screen
  1197.              */
  1198.             if (line_on_screen == NOTCURLINE)
  1199.                update_line( &w );
  1200.             else if (line_on_screen == CURLINE)
  1201.                show_curl_line( &w );
  1202.          }
  1203.       }
  1204.    }
  1205.    file->dirty = FALSE;
  1206. }
  1207.  
  1208.  
  1209. /*
  1210.  * Name:    show_curl_line
  1211.  * Purpose: show current line in curl color
  1212.  * Date:    January 16, 1992
  1213.  * Passed:  window:  pointer to current window
  1214.  */
  1215. void show_curl_line( TDE_WIN *window )
  1216. {
  1217. int  text_color;
  1218. int  dirty_color;
  1219.  
  1220.    if (window->visible  &&  g_status.screen_display) {
  1221.       text_color = g_display.text_color;
  1222.       dirty_color = g_display.dirty_color;
  1223.       g_display.dirty_color = g_display.text_color = g_display.curl_color;
  1224.       update_line( window );
  1225.       g_display.text_color = text_color;
  1226.       g_display.dirty_color = dirty_color;
  1227.    }
  1228. }
  1229.  
  1230.  
  1231. /*
  1232.  * Name:    dup_window_info
  1233.  * Purpose: Copy window info from one window pointer to another
  1234.  * Date:    June 5, 1991
  1235.  * Passed:  dw: destination window
  1236.  *          sw: source window
  1237.  */
  1238. void dup_window_info( TDE_WIN *dw, TDE_WIN *sw )
  1239. {
  1240.    memcpy( dw, sw, sizeof( TDE_WIN ) );
  1241. }
  1242.  
  1243.  
  1244. /*
  1245.  * Name:    adjust_windows_cursor
  1246.  * Purpose: A change has been made, make sure pointers are not ahead of
  1247.  *           or behind file.
  1248.  * Date:    June 5, 1991
  1249.  * Passed:  window:       pointer to current window
  1250.  *          line_change:  number of lines add to or subtracted from file
  1251.  * Notes:   If a file has been truncated in one window and there is another
  1252.  *           window open to the same file and its current line is near the
  1253.  *           end, the current line is reset to the last line of the file.
  1254.  */
  1255. void adjust_windows_cursor( TDE_WIN *window, long line_change )
  1256. {
  1257. register TDE_WIN *next;
  1258. long i;
  1259. file_infos *file;
  1260. MARKER *marker;
  1261. long length;
  1262.  
  1263.    file = window->file_info;
  1264.    length = file->length;
  1265.    next = g_status.window_list;
  1266.    while (next != NULL) {
  1267.       if (next != window) {
  1268.          if (next->file_info == file) {
  1269.             if (next->rline > length + 1) {
  1270.                next->rline = length;
  1271.                next->ll    = file->line_list_end;
  1272.                file->dirty = NOT_LOCAL;
  1273.             } else if (next->rline < 1) {
  1274.                next->rline = 1;
  1275.                next->cline = next->top_line + next->ruler;
  1276.                next->ll    = file->line_list;
  1277.                next->bin_offset = 0;
  1278.                file->dirty = NOT_LOCAL;
  1279.             }
  1280.             if (next->rline > window->rline  &&  line_change) {
  1281.                file->dirty = NOT_LOCAL;
  1282.                if (line_change < 0) {
  1283.                   for (i=line_change; i < 0 && next->ll->next != NULL; i++) {
  1284.                      next->bin_offset += next->ll->len;
  1285.                      next->ll = next->ll->next;
  1286.                   }
  1287.                } else if (line_change > 0) {
  1288.                   for (i=line_change; i > 0 && next->ll->prev != NULL; i--) {
  1289.                      next->ll = next->ll->prev;
  1290.                      next->bin_offset -= next->ll->len;
  1291.                   }
  1292.                }
  1293.             }
  1294.             if (next->rline < (next->cline -(next->top_line+next->ruler-1))) {
  1295.                next->cline = (int)next->rline+(next->top_line+next->ruler)-1;
  1296.                file->dirty = NOT_LOCAL;
  1297.             }
  1298.          }
  1299.       }
  1300.       next = next->next;
  1301.    }
  1302.  
  1303.    /*
  1304.     * now adjust any markers.
  1305.     */
  1306.    for (i=0; i<3; i++) {
  1307.       marker = &file->marker[ (int) i ];
  1308.       if (marker->rline > window->rline) {
  1309.          marker->rline += line_change;
  1310.          if (marker->rline < 1L)
  1311.             marker->rline = 1L;
  1312.          else if (marker->rline > length)
  1313.             marker->rline = length;
  1314.       }
  1315.    }
  1316. }
  1317.  
  1318.  
  1319. /*
  1320.  * Name:    first_non_blank
  1321.  * Purpose: To find the column of the first non-blank character
  1322.  * Date:    June 5, 1991
  1323.  * Passed:  s:    the string to search
  1324.  *          len:  length of string
  1325.  * Returns: the first non-blank column
  1326.  */
  1327. int  first_non_blank( text_ptr s, int len )
  1328. {
  1329. register int count = 0;
  1330.  
  1331.    if (s != NULL) {
  1332.       if (mode.inflate_tabs) {
  1333.          for (; len > 0 && (*s == ' ' || *s == '\t'); s++, len--) {
  1334.             if (*s != '\t')
  1335.                ++count;
  1336.             else
  1337.                count += mode.ptab_size - (count % mode.ptab_size);
  1338.          }
  1339.       } else {
  1340.          while (len-- > 0  &&  *s++ == ' ')
  1341.            ++count;
  1342.       }
  1343.    }
  1344.    return( count );
  1345. }
  1346.  
  1347.  
  1348. /*
  1349.  * Name:    find_end
  1350.  * Purpose: To find the last character in a line
  1351.  * Date:    October 31, 1992
  1352.  * Passed:  s:    the string to search
  1353.  *          len:  length of string
  1354.  * Returns: the first non-blank column
  1355.  */
  1356. int  find_end( text_ptr s, int len )
  1357. {
  1358. register int count = 0;
  1359.  
  1360.    if (s != NULL) {
  1361.       if (mode.inflate_tabs) {
  1362.          for (;len > 0; s++, len--) {
  1363.             if (*s == '\t')
  1364.                count += mode.ptab_size - (count % mode.ptab_size);
  1365.             else
  1366.                ++count;
  1367.          }
  1368.       } else
  1369.          count = len;
  1370.    }
  1371.    return( count );
  1372. }
  1373.  
  1374.  
  1375. /*
  1376.  * Name:    is_line_blank
  1377.  * Purpose: is line empty or does it only contain spaces?
  1378.  * Date:    November 28, 1991
  1379.  * Passed:  s:    the string to search
  1380.  *          len:  length of string
  1381.  * Returns: TRUE if line is blank or FALSE if something is in line
  1382.  */
  1383. int is_line_blank( text_ptr s, int len )
  1384. {
  1385.    if (s != NULL) {
  1386.       if (mode.inflate_tabs) {
  1387.         while (len > 0  &&  (*s == ' ' || *s == '\t')) {
  1388.            ++s;
  1389.            --len;
  1390.         }
  1391.       } else {
  1392.          while (len > 0  &&  *s == ' ') {
  1393.             ++s;
  1394.             --len;
  1395.          }
  1396.       }
  1397.    } else
  1398.       len = 0;
  1399.    return( len == 0 );
  1400. }
  1401.  
  1402.  
  1403. /*
  1404.  * Name:    page_up
  1405.  * Purpose: To move the cursor one page up the window
  1406.  * Date:    June 5, 1991
  1407.  * Passed:  window:  pointer to current window
  1408.  * Notes:   The cursor line is moved back the required number of lines
  1409.  *           towards the start of the file.
  1410.  *          If the start of the file is reached, then movement stops.
  1411.  */
  1412. int  page_up( TDE_WIN *window )
  1413. {
  1414. int  i;                 /* count of lines scanned */
  1415. int  rc = OK;           /* default return code */
  1416. register TDE_WIN *win;   /* put window pointer in a register */
  1417. long number;
  1418. long len;
  1419.  
  1420.    win = window;
  1421.    entab_linebuff( );
  1422.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1423.       return( ERROR );
  1424.    if (win->rline != (win->cline - (win->top_line + win->ruler - 1))) {
  1425.       i = win->cline - (win->top_line + win->ruler - 1);
  1426.       number = win->rline;
  1427.       if (( win->rline - i) < win->page)
  1428.          win->rline = (win->cline-(win->top_line + win->ruler -1)) + win->page;
  1429.       win->rline -= win->page;
  1430.       for (len =0, i=(int)(number - win->rline); i>0; i--)
  1431.          if (win->ll->prev != NULL) {
  1432.             win->ll = win->ll->prev;
  1433.             len -= win->ll->len;
  1434.          }
  1435.       win->file_info->dirty = LOCAL;
  1436.       win->bin_offset += len;
  1437.    } else
  1438.       rc = ERROR;
  1439.    cursor_sync( win );
  1440.    return( rc );
  1441. }
  1442.  
  1443.  
  1444. /*
  1445.  * Name:    page_down
  1446.  * Purpose: To move the cursor one page down the window
  1447.  * Date:    June 5, 1991
  1448.  * Passed:  window:  pointer to current window
  1449.  * Notes:   The cursor line is moved forwards the required number of lines
  1450.  *           towards the end of the file.
  1451.  *          If the end of the file is reached, then movement stops.
  1452.  */
  1453. int  page_down( TDE_WIN *window )
  1454. {
  1455. int  i;                 /* count of lines scanned so far */
  1456. int  k;
  1457. int  rc = OK;
  1458. long len;
  1459. register TDE_WIN *win;  /* put window pointer in a register */
  1460. line_list_ptr p;
  1461.  
  1462.    win = window;
  1463.    entab_linebuff( );
  1464.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1465.       return( ERROR );
  1466.    p = win->ll;
  1467.    k = win->cline - (win->top_line + win->ruler);
  1468.    for (len=i=0; i < win->page && p->next != NULL; i++, k++, p=p->next)
  1469.       if (p->len != EOF)
  1470.          len += p->len;
  1471.    if (k >= win->page) {
  1472.       win->rline += i;
  1473.       win->cline = win->cline + i - win->page;
  1474.       win->bin_offset += len;
  1475.       win->ll = p;
  1476.       win->file_info->dirty = LOCAL;
  1477.    } else
  1478.       rc = ERROR;
  1479.    cursor_sync( win );
  1480.    return( rc );
  1481. }
  1482.  
  1483.  
  1484. /*
  1485.  * Name:    scroll_down
  1486.  * Purpose: scroll window down one line
  1487.  * Date:    June 5, 1991
  1488.  * Passed:  window:  pointer to current window
  1489.  * Notes:   If there is a line to scroll_down, make the window LOCAL dirty.
  1490.  *          We have to redraw the screen anyway, so don't update here.
  1491.  */
  1492. int  scroll_down( TDE_WIN *window )
  1493. {
  1494. int  rc = OK;
  1495. register TDE_WIN *win;   /* put window pointer in a register */
  1496.  
  1497.    win = window;
  1498.    entab_linebuff( );
  1499.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1500.       return( ERROR );
  1501.    if (win->cline == win->top_line + win->ruler) {
  1502.       if (win->ll->next != NULL) {
  1503.          ++win->rline;
  1504.          win->bin_offset += win->ll->len;
  1505.          win->ll = win->ll->next;
  1506.          win->file_info->dirty = LOCAL;
  1507.       } else
  1508.          rc = ERROR;
  1509.    } else {
  1510.       --win->cline;
  1511.       win->file_info->dirty = LOCAL;
  1512.    }
  1513.    cursor_sync( win );
  1514.    return( rc );
  1515. }
  1516.  
  1517.  
  1518. /*
  1519.  * Name:    scroll_up
  1520.  * Purpose: To scroll the window up one line
  1521.  * Date:    June 5, 1991
  1522.  * Passed:  window:  pointer to current window
  1523.  * Notes:   If this is the first page, then update screen here.  Else, make
  1524.  *           the window LOCAL dirty because we have to redraw screen.
  1525.  */
  1526. int  scroll_up( TDE_WIN *window )
  1527. {
  1528. int  rc = OK;
  1529. register TDE_WIN *win;   /* put window pointer in a register */
  1530.  
  1531.    win = window;
  1532.    entab_linebuff( );
  1533.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1534.       return( ERROR );
  1535.    if (win->rline > 1) {
  1536.       if (win->rline == (win->cline - (win->top_line + win->ruler - 1))) {
  1537.          if (!mode.sync)
  1538.             update_line( win );
  1539.          win->ll = win->ll->prev;
  1540.          win->bin_offset -= win->ll->len;
  1541.          --win->rline;
  1542.          --win->cline;
  1543.          if (!mode.sync)
  1544.             show_curl_line( win );
  1545.       } else {
  1546.          if (win->cline == win->bottom_line) {
  1547.             --win->rline;
  1548.             win->ll = win->ll->prev;
  1549.             win->bin_offset -= win->ll->len;
  1550.             win->file_info->dirty = LOCAL;
  1551.          } else {
  1552.             ++win->cline;
  1553.             win->file_info->dirty = LOCAL;
  1554.          }
  1555.       }
  1556.    } else
  1557.      rc = ERROR;
  1558.    cursor_sync( win );
  1559.    return( rc );
  1560. }
  1561.  
  1562.  
  1563. /*
  1564.  * Name:    pan_up
  1565.  * Purpose: To leave cursor on same logical line and scroll text up
  1566.  * Date:    September 1, 1991
  1567.  * Passed:  window:  pointer to current window
  1568.  * Notes:   If cursor is on first page then do not scroll.
  1569.  */
  1570. int  pan_up( TDE_WIN *window )
  1571. {
  1572. int  rc = OK;
  1573. register TDE_WIN *win;   /* put window pointer in a register */
  1574.  
  1575.    win = window;
  1576.    entab_linebuff( );
  1577.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1578.       return( ERROR );
  1579.  
  1580.    /*
  1581.     * see if cursor is on the first page. if it's not then pan_up.
  1582.     */
  1583.    if (win->rline != (win->cline+1 - (win->top_line + win->ruler))) {
  1584.       if (win->rline > 1) {
  1585.          --win->rline;
  1586.          win->ll = win->ll->prev;
  1587.          win->bin_offset -= win->ll->len;
  1588.          win->file_info->dirty = LOCAL;
  1589.       }
  1590.    } else
  1591.       rc = ERROR;
  1592.    cursor_sync( win );
  1593.    return( rc );
  1594. }
  1595.  
  1596.  
  1597. /*
  1598.  * Name:    pan_down
  1599.  * Purpose: To leave cursor on same logical line and scroll text down
  1600.  * Date:    September 1, 1991
  1601.  * Passed:  window:  pointer to current window
  1602.  * Notes:   If cursor is on last line in file then do not scroll.
  1603.  */
  1604. int  pan_down( TDE_WIN *window )
  1605. {
  1606. int  rc = OK;
  1607. register TDE_WIN *win;   /* put window pointer in a register */
  1608.  
  1609.    win = window;
  1610.    entab_linebuff( );
  1611.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1612.       return( ERROR );
  1613.    if (win->ll->len != EOF) {
  1614.       ++win->rline;
  1615.       win->bin_offset += win->ll->len;
  1616.       win->ll = win->ll->next;
  1617.       win->file_info->dirty = LOCAL;
  1618.    } else
  1619.       rc = ERROR;
  1620.    cursor_sync( win );
  1621.    return( rc );
  1622. }
  1623.  
  1624.  
  1625. /*
  1626.  * Name:    show_window_header
  1627.  * Purpose: show file stuff in window header
  1628.  * Date:    June 5, 1991
  1629.  * Passed:  window:  pointer to current window
  1630.  * Notes:   Clear line and display header in a lite bar
  1631.  */
  1632. void show_window_header( TDE_WIN *window )
  1633. {
  1634. register TDE_WIN *win;          /* put window pointer in a register */
  1635. int  len;
  1636. char temp[MAX_COLS+2];
  1637.  
  1638.    win = window;
  1639.    len = win->vertical ? win->end_col + 1 - win->start_col : win->end_col;
  1640.  
  1641.    assert( len >= 0 );
  1642.    assert( len <= g_display.ncols );
  1643.    memset( temp, ' ', len );
  1644.    temp[len] = '\0';
  1645.    s_output( temp, win->top_line-1, win->start_col, g_display.head_color );
  1646.    show_window_number_letter( win );
  1647.    show_window_fname( win );
  1648.    show_crlf_mode( win );
  1649.    show_size( win );
  1650.    show_line_col( win );
  1651. }
  1652.  
  1653.  
  1654. /*
  1655.  * Name:    show_window_number_letter
  1656.  * Purpose: show file number and letter of window in lite bar
  1657.  * Date:    June 5, 1991
  1658.  * Passed:  window:  pointer to current window
  1659.  */
  1660. void show_window_number_letter( TDE_WIN *window )
  1661. {
  1662. int  col;
  1663. char temp[10];
  1664. register TDE_WIN *win;   /* put window pointer in a register */
  1665.  
  1666.    win = window;
  1667.    col = win->start_col;
  1668.    s_output( "   ", win->top_line-1, col, g_display.head_color );
  1669.    my_ltoa( win->file_info->file_no, temp, 10 );
  1670.    s_output( temp, win->top_line-1, strlen( temp ) > 1 ? col : col+1,
  1671.              g_display.head_color );
  1672.    c_output( win->letter, col+2, win->top_line-1, g_display.head_color );
  1673. }
  1674.  
  1675.  
  1676. #if defined( __UNIX__ )
  1677. /*
  1678.  **********************************************************************
  1679.  ******************************  PART 1  ******************************
  1680.  **********************************************************************
  1681.  *
  1682.  * Let's try to make unix have the look and feel of a PC.
  1683.  */
  1684.  
  1685.  
  1686. /*
  1687.  * Name:     show_window_fname
  1688.  * Purpose:  show file name in window header.
  1689.  * Date:     June 5, 1991
  1690.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  1691.  * Passed:   window:  pointer to current window
  1692.  * Notes:    Clear name field and display name in a lite bar
  1693.  */
  1694. void show_window_fname( TDE_WIN *window )
  1695. {
  1696. register int  fattr;
  1697. char *p;
  1698. register TDE_WIN *win;          /* put window pointer in a register */
  1699. int  col;
  1700. int  len;
  1701. char temp[PATH_MAX+2];
  1702.  
  1703.    win = window;
  1704.    col = win->start_col;
  1705.    len = win->vertical ? 11 : FNAME_LENGTH;
  1706.  
  1707.    assert( len >= 0 );
  1708.    assert( len <= g_display.ncols );
  1709.  
  1710.    memset( temp, ' ', len );
  1711.    temp[len] = '\0';
  1712.    s_output( temp, win->top_line-1, col+5, g_display.head_color );
  1713.  
  1714.    assert( strlen( win->file_info->file_name ) < (size_t)g_display.ncols );
  1715.  
  1716.    strcpy( temp, win->file_info->file_name );
  1717.    p = temp;
  1718.    len = strlen( temp );
  1719.    if (win->vertical) {
  1720.       for (p = temp + len; *(p-1) != '\\' && p>temp; )
  1721.          --p;
  1722.       if (strlen( p ) > 11)
  1723.          *(p + 11) = '\0';
  1724.    } else {
  1725.       if (len > FNAME_LENGTH)
  1726.          p = temp + len - (FNAME_LENGTH-1);
  1727.    }
  1728.    s_output( p, win->top_line-1, col+5, g_display.head_color );
  1729.    if (!win->vertical) {
  1730.       fattr = win->file_info->file_attrib;
  1731.       p = temp;
  1732.       *p++ = (char)(fattr & S_IRUSR  ? L_UNIX_READ    : '-');
  1733.       *p++ = (char)(fattr & S_IWUSR  ? L_UNIX_WRITE   : '-');
  1734.       *p++ = (char)(fattr & S_IXUSR  ? L_UNIX_EXECUTE : '-');
  1735.       *p   = '\0';
  1736.       s_output( temp, win->top_line-1, col+51, g_display.head_color );
  1737.    }
  1738. }
  1739.  
  1740. #else
  1741. /*
  1742.  **********************************************************************
  1743.  ******************************  PART 2  ******************************
  1744.  **********************************************************************
  1745.  *
  1746.  * Calls to BIOS and writes to PC hardware.
  1747.  */
  1748.  
  1749.  
  1750. /*
  1751.  * Name:     show_window_fname
  1752.  * Purpose:  show file name in window header.
  1753.  * Date:     June 5, 1991
  1754.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  1755.  * Passed:   window:  pointer to current window
  1756.  * Notes:    Clear name field and display name in a lite bar
  1757.  */
  1758. void show_window_fname( TDE_WIN *window )
  1759. {
  1760. register int  fattr;
  1761. char *p;
  1762. register TDE_WIN *win;          /* put window pointer in a register */
  1763. int  col;
  1764. int  len;
  1765. char temp[MAX_COLS+2];
  1766.  
  1767.    win = window;
  1768.    col = win->start_col;
  1769.    len = win->vertical ? 11 : FNAME_LENGTH;
  1770.  
  1771.    assert( len >= 0 );
  1772.    assert( len <= g_display.ncols );
  1773.  
  1774.    memset( temp, ' ', len );
  1775.    temp[len] = '\0';
  1776.    s_output( temp, win->top_line-1, col+5, g_display.head_color );
  1777.  
  1778.    assert( strlen( win->file_info->file_name ) < (size_t)g_display.ncols );
  1779.  
  1780.    strcpy( temp, win->file_info->file_name );
  1781.    p = temp;
  1782.    if (win->vertical) {
  1783.       len = strlen( temp );
  1784.       for (p = temp + len; *(p-1) != ':' && *(p-1) != '\\' && p>temp; )
  1785.          --p;
  1786.    } else {
  1787.       temp[FNAME_LENGTH] = '\0';
  1788.       p = temp;
  1789.    }
  1790.    s_output( p, win->top_line-1, col+5, g_display.head_color );
  1791.    if (!win->vertical) {
  1792.       fattr = win->file_info->file_attrib;
  1793.       p = temp;
  1794.       *p++ = (char)(fattr & ARCHIVE   ? L_DOS_ARCHIVE   : '-');
  1795.       *p++ = (char)(fattr & SYSTEM    ? L_DOS_SYSTEM    : '-');
  1796.       *p++ = (char)(fattr & HIDDEN    ? L_DOS_HIDDEN    : '-');
  1797.       *p++ = (char)(fattr & READ_ONLY ? L_DOS_READ_ONLY : '-');
  1798.       *p   = '\0';
  1799.       s_output( temp, win->top_line-1, col+51, g_display.head_color );
  1800.    }
  1801. }
  1802.  
  1803. #endif
  1804.  
  1805. /*
  1806.  * Name:     show_crlf_mode
  1807.  * Purpose:  display state of crlf flag
  1808.  * Date:     June 5, 1991
  1809.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  1810.  */
  1811. void show_crlf_mode( TDE_WIN *window )
  1812. {
  1813. char temp[MAX_COLS+2];
  1814.  
  1815.    if (!window->vertical) {
  1816.       switch (window->file_info->crlf) {
  1817.          case LF :
  1818.             strcpy( temp, mode_lf );
  1819.             break;
  1820.          case CRLF :
  1821.             strcpy( temp, mode_crlf );
  1822.             break;
  1823.          case BINARY :
  1824.             strcpy( temp, mode_bin );
  1825.             break;
  1826.          default :
  1827.             assert( FALSE );
  1828.       }
  1829.       s_output( temp, window->top_line-1, window->start_col+56,
  1830.                 g_display.head_color );
  1831.    }
  1832. }
  1833.  
  1834.  
  1835. /*
  1836.  * Name:    show_size
  1837.  * Purpose: show number of lines in file
  1838.  * Date:    June 5, 1991
  1839.  * Passed:  window:  pointer to current window
  1840.  */
  1841. void show_size( TDE_WIN *window )
  1842. {
  1843. char csize[20];
  1844.  
  1845.    if (!window->vertical  &&  window->file_info->crlf != BINARY) {
  1846.       s_output( "       ", window->top_line-1, 61, g_display.head_color );
  1847.       my_ltoa( window->file_info->length, csize, 10 );
  1848.       s_output( csize, window->top_line-1, 61, g_display.head_color );
  1849.    }
  1850. }
  1851.  
  1852.  
  1853. /*
  1854.  * Name:    quit
  1855.  * Purpose: To close the current window without saving the current file.
  1856.  * Date:    June 5, 1991
  1857.  * Passed:  window:  pointer to current window
  1858.  * Notes:   If the file has been modified but not saved, then the user is
  1859.  *           given a second chance before the changes are discarded.
  1860.  *          Note that this is only necessary if this is the last window
  1861.  *           that refers to the file.  If another window still refers to
  1862.  *           the file, then the check can be left until later.
  1863.  */
  1864. int  quit( TDE_WIN *window )
  1865. {
  1866. int  prompt_line;
  1867. register file_infos *file;
  1868. TDE_WIN *wp;
  1869. int  count = 0;
  1870. int  rc = OK;
  1871. #if defined( __UNIX__ )
  1872.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  1873. #else
  1874.  char display_buff[(MAX_COLS+2)*2];
  1875. #endif
  1876.  
  1877.    assert( window != NULL );
  1878.  
  1879.    entab_linebuff( );
  1880.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  1881.       return( ERROR );
  1882.    prompt_line = window->bottom_line;
  1883.    file = window->file_info;
  1884.    for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  1885.       if (wp->file_info == file && wp->visible)
  1886.          ++count;
  1887.    }
  1888.    if (file->modified && count == 1) {
  1889.       save_screen_line( 0, prompt_line, display_buff );
  1890.       /*
  1891.        * abandon changes (y/n)
  1892.        */
  1893.       set_prompt( utils12, prompt_line );
  1894.       if (get_yn( ) != A_YES)
  1895.          rc = ERROR;
  1896.       restore_screen_line( 0, prompt_line, display_buff );
  1897.    }
  1898.  
  1899.    /*
  1900.     * remove window, allocate screen lines to other windows etc
  1901.     */
  1902.    if (rc == OK)
  1903.       finish( window );
  1904.    return( OK );
  1905. }
  1906.  
  1907.  
  1908. /*
  1909.  * Name:    move_up
  1910.  * Purpose: To move the cursor up one line
  1911.  * Date:    June 5, 1991
  1912.  * Passed:  window:  pointer to current window
  1913.  * Notes:   If the cursor is at the top of the window, then the file must
  1914.  *           be scrolled down.
  1915.  */
  1916. int  move_up( TDE_WIN *window )
  1917. {
  1918. int  rc = OK;
  1919. register TDE_WIN *win;   /* put window pointer in a register */
  1920. int  at_top = FALSE;    /* is cline at top of screen? */
  1921.  
  1922.    win = window;
  1923.    entab_linebuff( );
  1924.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1925.       return( ERROR );
  1926.  
  1927.    /*
  1928.     * if no previous line, give up
  1929.     */
  1930.    if (win->rline > 1) {
  1931.       if (win->cline == win->top_line + win->ruler) {
  1932.          win->file_info->dirty = LOCAL;
  1933.          at_top = TRUE;
  1934.       }
  1935.       if (!at_top)
  1936.          update_line( win );
  1937.       --win->rline;             /* ALWAYS decrement line counter */
  1938.       win->ll = win->ll->prev;
  1939.       win->bin_offset -= win->ll->len;
  1940.       if (!at_top) {
  1941.          --win->cline;          /* we aren't at top of screen - so move up */
  1942.          show_curl_line( win );
  1943.       }
  1944.    } else
  1945.       rc = ERROR;
  1946.    cursor_sync( win );
  1947.    return( rc );
  1948. }
  1949.  
  1950.  
  1951. /*
  1952.  * Name:    move_down
  1953.  * Purpose: To move the cursor down one line
  1954.  * Date:    June 5, 1991
  1955.  * Passed:  window:  pointer to current window
  1956.  * Notes:   If the cursor is at the bottom of the window, then the file must
  1957.  *           be scrolled up.   If the cursor is at the bottom of the file,
  1958.  *           then scroll line up until it is at top of screen.
  1959.  */
  1960. int  move_down( TDE_WIN *window )
  1961. {
  1962. int  rc;
  1963.  
  1964.    rc = prepare_move_down( window );
  1965.    cursor_sync( window );
  1966.    return( rc );
  1967. }
  1968.  
  1969.  
  1970. /*
  1971.  * Name:    prepare_move_down
  1972.  * Purpose: Do the stuff needed to move the cursor down one line.
  1973.  * Date:    June 5, 1991
  1974.  * Passed:  window:  pointer to current window
  1975.  * Notes:   Put all the stuff needed to move the cursor down one line in
  1976.  *           one function, so several functions can use the guts of the
  1977.  *           algorithm.
  1978.  */
  1979. int  prepare_move_down( TDE_WIN *window )
  1980. {
  1981. int  rc = OK;
  1982. register TDE_WIN *win;   /* put window pointer in a register */
  1983. int  at_bottom = FALSE; /* is cline at bottom of screen */
  1984.  
  1985.    win = window;
  1986.    entab_linebuff( );
  1987.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  1988.       return( ERROR );
  1989.    if (win->cline == win->bottom_line) {
  1990.       win->file_info->dirty = LOCAL;
  1991.       at_bottom = TRUE;
  1992.    }
  1993.    if (!at_bottom)
  1994.       update_line( win );
  1995.    if (win->ll->len != EOF) {
  1996.       win->bin_offset += win->ll->len;
  1997.       ++win->rline;             /* ALWAYS increment line counter */
  1998.       win->ll = win->ll->next;
  1999.       if (!at_bottom) {
  2000.          ++win->cline;          /* if not at bottom of screen move down */
  2001.          show_curl_line( win );
  2002.       }
  2003.    } else if (win->cline > win->top_line + win->ruler) {
  2004.       --win->cline;
  2005.       win->file_info->dirty = LOCAL;
  2006.       rc = ERROR;
  2007.    } else
  2008.       rc = ERROR;
  2009.    return( rc );
  2010. }
  2011.  
  2012.  
  2013. /*
  2014.  * Name:    move_left
  2015.  * Purpose: To move the cursor left one character
  2016.  * Date:    June 5, 1991
  2017.  * Passed:  window:  pointer to current window
  2018.  * Notes:   If the cursor is already at the left of the screen, then
  2019.  *           scroll horizontally if we're not at beginning of line.
  2020.  */
  2021. int  move_left( TDE_WIN *window )
  2022. {
  2023. int  new_ruler = FALSE;
  2024.  
  2025.    if (window->ccol > window->start_col) {
  2026.       show_ruler_char( window );
  2027.       --window->ccol;
  2028.       --window->rcol;
  2029.    } else if (window->ccol == window->start_col && window->rcol > 0) {
  2030.       --window->rcol;
  2031.       --window->bcol;
  2032.       window->file_info->dirty = LOCAL;
  2033.       new_ruler = TRUE;
  2034.    }
  2035.    cursor_sync( window );
  2036.    if (new_ruler) {
  2037.       make_ruler( window );
  2038.       show_ruler( window );
  2039.    }
  2040.    return( OK );
  2041. }
  2042.  
  2043.  
  2044. /*
  2045.  * Name:    move_right
  2046.  * Purpose: To move the cursor right one character
  2047.  * Date:    June 5, 1991
  2048.  * Passed:  window:  pointer to current window
  2049.  * Notes:   If the cursor is already at the right of the screen (logical
  2050.  *          column 80) then scroll horizontally right.
  2051.  */
  2052. int  move_right( TDE_WIN *window )
  2053. {
  2054. int  new_ruler = FALSE;
  2055.  
  2056.    if (window->rcol < g_display.line_length - 1) {
  2057.       if (window->ccol < window->end_col) {
  2058.          show_ruler_char( window );
  2059.          ++window->ccol;
  2060.          ++window->rcol;
  2061.       } else if (window->ccol == window->end_col) {
  2062.          ++window->rcol;
  2063.          ++window->bcol;
  2064.          window->file_info->dirty = LOCAL;
  2065.          new_ruler = TRUE;
  2066.       }
  2067.    }
  2068.    cursor_sync( window );
  2069.    if (new_ruler) {
  2070.       make_ruler( window );
  2071.       show_ruler( window );
  2072.    }
  2073.    return( OK );
  2074. }
  2075.  
  2076.  
  2077. /*
  2078.  * Name:    pan_left
  2079.  * Purpose: To pan the screen left one character
  2080.  * Date:    January 5, 1992
  2081.  * Passed:  window:  pointer to current window
  2082.  */
  2083. int  pan_left( TDE_WIN *window )
  2084. {
  2085. /*
  2086.  * if (window->bcol == 0) {
  2087.  *    if (window->ccol > window->start_col) {
  2088.  *       show_ruler_char( window );
  2089.  *       --window->ccol;
  2090.  *       --window->rcol;
  2091.  *    }
  2092.  * } else if (window->bcol > 0 ) {
  2093.  * * *  Scroll window left function:
  2094.  * * *      --window->bcol;
  2095.  * * *      if (window->ccol < g_display.ncols - 1)
  2096.  * * *         ++window->ccol;
  2097.  * * *      else
  2098.  * * *         --window->rcol;
  2099.  */
  2100.    if (window->bcol > 0 ) {
  2101.       --window->bcol;
  2102.       --window->rcol;
  2103.       window->file_info->dirty = LOCAL;
  2104.       make_ruler( window );
  2105.       show_ruler( window );
  2106.    }
  2107.    cursor_sync( window );
  2108.    return( OK );
  2109. }
  2110.  
  2111.  
  2112. /*
  2113.  * Name:    pan_right
  2114.  * Purpose: To pan the screen right one character
  2115.  * Date:    January 5, 1992
  2116.  * Passed:  window:  pointer to current window
  2117.  */
  2118. int  pan_right( TDE_WIN *window )
  2119. {
  2120.    if (window->rcol < g_display.line_length - 1) {
  2121. /*
  2122.  *      scroll screen right function:
  2123.  *      if (window->ccol > 0)
  2124.  *         --window->ccol;
  2125.  *      else
  2126.  *         ++window->rcol;
  2127.  */
  2128.       ++window->rcol;
  2129.       ++window->bcol;
  2130.       window->file_info->dirty = LOCAL;
  2131.       make_ruler( window );
  2132.       show_ruler( window );
  2133.    }
  2134.    cursor_sync( window );
  2135.    return( OK );
  2136. }
  2137.  
  2138.  
  2139. /*
  2140.  * Name:    word_left
  2141.  * Purpose: To move the cursor left one word
  2142.  * Date:    June 5, 1991
  2143.  * Passed:  window:  pointer to current window
  2144.  * Notes:   Words are considered strings of letters, numbers and underscores,
  2145.  *          which must be separated by other characters.
  2146.  */
  2147. int  word_left( TDE_WIN *window )
  2148. {
  2149. text_ptr p;             /* text pointer */
  2150. int  len;               /* length of current line */
  2151. int  rc;
  2152. int  tabs;
  2153. int  rcol;
  2154. register int r1;
  2155. long rline;
  2156. line_list_ptr ll;
  2157. TDE_WIN w;
  2158.  
  2159.    entab_linebuff( );
  2160.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2161.       return( ERROR );
  2162.    rc = OK;
  2163.    dup_window_info( &w, window );
  2164.    rline = window->rline;
  2165.    rcol  = window->rcol;
  2166.    ll = window->ll;
  2167.    if (ll->len != EOF) {
  2168.       p   = ll->line;
  2169.       len = ll->len;
  2170.  
  2171.       tabs = mode.inflate_tabs;
  2172.       r1 =  tabs ? entab_adjust_rcol( p, len, rcol ) : rcol;
  2173.  
  2174.       if (p != NULL  &&  r1 > 0  &&  r1 >= len  &&
  2175.                                       !myiswhitespc( *(p + len - 1) )) {
  2176.          r1 = len - 1;
  2177.          p += r1;
  2178.          for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2179.          ++r1;
  2180.          rcol = tabs ? detab_adjust_rcol( ll->line, r1 ) : r1;
  2181.          check_virtual_col( window, rcol, rcol );
  2182.          make_ruler( window );
  2183.          show_ruler( window );
  2184.       } else {
  2185.          r1 =  r1 >= len ? len-1 : r1;
  2186.          if (r1 >= 0)
  2187.             p += r1;
  2188.          if (p != NULL  &&  r1 > 0  &&  !myiswhitespc( *p )  &&
  2189.                                           !myiswhitespc( *(p-1) )) {
  2190.             for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2191.             ++r1;
  2192.             rcol = tabs ? detab_adjust_rcol( ll->line, r1 ) : r1;
  2193.             check_virtual_col( window, rcol, rcol );
  2194.             make_ruler( window );
  2195.             show_ruler( window );
  2196.          } else {
  2197.  
  2198.             /*
  2199.              * if we are on the first letter of a word, get off.
  2200.              */
  2201.             if (p != NULL)
  2202.                for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2203.  
  2204.             /*
  2205.              * go to the next line if word begins at 1st col in line.
  2206.              */
  2207.             if (r1 < 0) {
  2208.                if (ll->prev != NULL) {
  2209.                   --rline;
  2210.                   ll = ll->prev;
  2211.                   p = ll->line;
  2212.                   r1 = ll->len - 1;
  2213.                   if (r1 >= 0)
  2214.                      p += r1;
  2215.                } else
  2216.                   rc = ERROR;
  2217.             }
  2218.  
  2219.             /*
  2220.              * skip all blanks until we get to a previous word
  2221.              */
  2222.             while (rc == OK  &&  (p == NULL  ||  (p != NULL  &&
  2223.                                                   myiswhitespc( *p )))) {
  2224.                for (; r1 >= 0 && myiswhitespc( *p ); r1--, p--);
  2225.                if (r1 < 0) {
  2226.                   if (ll->prev != NULL) {
  2227.                      --rline;
  2228.                      ll = ll->prev;
  2229.                      p = ll->line;
  2230.                      r1 = ll->len - 1;
  2231.                      if (r1 >= 0)
  2232.                         p += r1;
  2233.                   } else
  2234.                      rc = ERROR;
  2235.                } else
  2236.                   break;
  2237.             }
  2238.  
  2239.             /*
  2240.              * now, find the beginning of the word.
  2241.              */
  2242.             if (rc == OK  &&  p != NULL) {
  2243.                for (; r1 >= 0 && !myiswhitespc( *p ); r1--, p--);
  2244.                r1++;
  2245.                bin_offset_adjust( window, rline );
  2246.                find_adjust( window, ll, rline, r1 );
  2247.                if (rline != w.rline && !window->file_info->dirty) {
  2248.                   update_line( &w );
  2249.                   show_curl_line( window );
  2250.                }
  2251.                make_ruler( window );
  2252.                show_ruler( window );
  2253.             } else
  2254.                rc = ERROR;
  2255.          }
  2256.       }
  2257.    } else
  2258.       rc = ERROR;
  2259.  
  2260.    cursor_sync( window );
  2261.    return( rc );
  2262. }
  2263.  
  2264.  
  2265. /*
  2266.  * Name:    word_right
  2267.  * Purpose: To move the cursor right one word
  2268.  * Date:    June 5, 1991
  2269.  * Passed:  window:  pointer to current window
  2270.  * Notes:   Words are considered strings of letters, numbers and underscores,
  2271.  *           which must be separated by other characters.
  2272.  */
  2273. int  word_right( TDE_WIN *window )
  2274. {
  2275. int  len;               /* length of current line */
  2276. text_ptr p;             /* text pointer */
  2277. int  rc;
  2278. int  tabs;
  2279. int  rcol;
  2280. register int r1;
  2281. TDE_WIN w;
  2282. line_list_ptr ll;
  2283. long rline;
  2284.  
  2285.    entab_linebuff( );
  2286.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2287.       return( ERROR );
  2288.    rc = OK;
  2289.    dup_window_info( &w, window );
  2290.    rline = window->rline;
  2291.    r1 = rcol = window->rcol;
  2292.    ll    = window->ll;
  2293.    if (ll->len != EOF) {
  2294.       p   = ll->line;
  2295.       len = ll->len;
  2296.  
  2297.       tabs = mode.inflate_tabs;
  2298.       r1   =  tabs ? entab_adjust_rcol( p, len, rcol ) : rcol;
  2299.  
  2300.       /*
  2301.        * if rcol is past EOL, move it to EOL
  2302.        */
  2303.       r1 =  r1 >= len ? len-1 : r1;
  2304.       if (r1 >= 0)
  2305.          p += r1;
  2306.  
  2307.       /*
  2308.        * if cursor is on a word, find end of word.
  2309.        */
  2310.       if (p != NULL)
  2311.          for (; r1 < len && !myiswhitespc( *p ); r1++, p++);
  2312.       else
  2313.          r1 = len;
  2314.  
  2315.       /*
  2316.        * go to the next line if word ends at eol.
  2317.        */
  2318.       if (r1 == len) {
  2319.          ++rline;
  2320.          ll = ll->next;
  2321.          if (ll->len != EOF) {
  2322.             p = ll->line;
  2323.             len = ll->len;
  2324.             r1 = 0;
  2325.          } else
  2326.             rc = ERROR;
  2327.       }
  2328.  
  2329.       /*
  2330.        * now, go forward thru the file looking for the first letter of word.
  2331.        */
  2332.       while (rc == OK && (p == NULL  ||  (p != NULL && myiswhitespc( *p )))) {
  2333.          for (; r1 < len && myiswhitespc( *p ); r1++, p++);
  2334.          if (r1 == len) {
  2335.             ++rline;
  2336.             ll = ll->next;
  2337.             if (ll->len != EOF) {
  2338.                p = ll->line;
  2339.                len = ll->len;
  2340.                r1 = 0;
  2341.             } else
  2342.                rc = ERROR;
  2343.          } else
  2344.             break;
  2345.       }
  2346.    } else
  2347.       rc = ERROR;
  2348.  
  2349.    if (rc == OK) {
  2350.       bin_offset_adjust( window, rline );
  2351.       find_adjust( window, ll, rline, r1 );
  2352.       make_ruler( window );
  2353.       show_ruler( window );
  2354.    }
  2355.  
  2356.    if (rline != w.rline && !window->file_info->dirty) {
  2357.       update_line( &w );
  2358.       show_curl_line( window );
  2359.    }
  2360.    cursor_sync( window );
  2361.    return( rc );
  2362. }
  2363.  
  2364.  
  2365. /*
  2366.  * Name:    next_dirty_line
  2367.  * Purpose: To move the cursor to the next dirty line, if it exists
  2368.  * Date:    April 1, 1993
  2369.  * Passed:  window:  pointer to current window
  2370.  */
  2371. int  next_dirty_line( TDE_WIN *window )
  2372. {
  2373. int  rc;
  2374. line_list_ptr ll;
  2375. long rline;
  2376. long bin_offset;       /* binary offset */
  2377. TDE_WIN w;
  2378.  
  2379.    entab_linebuff( );
  2380.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2381.       return( ERROR );
  2382.    rc = OK;
  2383.    dup_window_info( &w, window );
  2384.    rline = window->rline;
  2385.    ll = window->ll;
  2386.    bin_offset = window->bin_offset;
  2387.    if (ll->len != EOF) {
  2388.       while (rc == OK) {
  2389.          if (ll->len != EOF) {
  2390.             ++rline;
  2391.             bin_offset += ll->len;
  2392.             ll = ll->next;
  2393.             if (ll->dirty == TRUE)
  2394.                break;
  2395.          } else
  2396.             rc = ERROR;
  2397.       }
  2398.    } else
  2399.       rc = ERROR;
  2400.  
  2401.    if (rc == OK) {
  2402.       window->bin_offset = bin_offset;
  2403.       find_adjust( window, ll, rline, window->rcol );
  2404.       make_ruler( window );
  2405.       show_ruler( window );
  2406.    } else
  2407.       error( WARNING, window->bottom_line, utils16 );
  2408.  
  2409.    if (rline != w.rline && !window->file_info->dirty) {
  2410.       update_line( &w );
  2411.       show_curl_line( window );
  2412.    }
  2413.    cursor_sync( window );
  2414.    return( rc );
  2415. }
  2416.  
  2417.  
  2418. /*
  2419.  * Name:    prev_dirty_line
  2420.  * Purpose: To move the cursor to the prev dirty line, if it exists
  2421.  * Date:    April 1, 1993
  2422.  * Passed:  window:  pointer to current window
  2423.  */
  2424. int  prev_dirty_line( TDE_WIN *window )
  2425. {
  2426. int  rc;
  2427. line_list_ptr ll;
  2428. long rline;
  2429. long bin_offset;        /* binary offset */
  2430. TDE_WIN w;
  2431.  
  2432.    entab_linebuff( );
  2433.    if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  2434.       return( ERROR );
  2435.    rc = OK;
  2436.    dup_window_info( &w, window );
  2437.    rline = window->rline;
  2438.    ll = window->ll;
  2439.    bin_offset = window->bin_offset;
  2440.    if (ll->prev != NULL) {
  2441.       while (rc == OK) {
  2442.          if (ll->prev != NULL) {
  2443.             --rline;
  2444.             ll = ll->prev;
  2445.             bin_offset -= ll->len;
  2446.             if (ll->dirty == TRUE)
  2447.                break;
  2448.          } else
  2449.             rc = ERROR;
  2450.       }
  2451.    } else
  2452.       rc = ERROR;
  2453.  
  2454.    if (rc == OK) {
  2455.       window->bin_offset = bin_offset;
  2456.       find_adjust( window, ll, rline, window->rcol );
  2457.       make_ruler( window );
  2458.       show_ruler( window );
  2459.    } else
  2460.       error( WARNING, window->bottom_line, utils16 );
  2461.  
  2462.    if (rline != w.rline && !window->file_info->dirty) {
  2463.       update_line( &w );
  2464.       show_curl_line( window );
  2465.    }
  2466.    cursor_sync( window );
  2467.    return( rc );
  2468. }
  2469.  
  2470.  
  2471. /*
  2472.  * Name:    center_window
  2473.  * Purpose: To place the current line or cursor in the center of a window.
  2474.  * Date:    June 5, 1991
  2475.  * Passed:  window:  pointer to current window
  2476.  */
  2477. int  center_window( TDE_WIN *window )
  2478. {
  2479. int  center;
  2480. int  center_line;
  2481. int  diff;
  2482. register file_infos *file;
  2483. register TDE_WIN *win;           /* put window pointer in a register */
  2484.  
  2485.    win = window;
  2486.    file = win->file_info;
  2487.    center = (win->bottom_line + 1 - win->top_line) / 2 - win->ruler;
  2488.    center_line = win->top_line + win->ruler + center;
  2489.    diff = center_line - win->cline;
  2490.    entab_linebuff( );
  2491.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2492.       return( ERROR );
  2493.    if (g_status.command == CenterWindow) {
  2494.       if (diff > 0) {
  2495.          if (win->rline + diff <= file->length) {
  2496.             update_line( win );
  2497.             win->cline += diff;
  2498.             win->rline += diff;
  2499.             for (; diff > 0; diff--) {
  2500.                win->bin_offset += win->ll->len;
  2501.                win->ll = win->ll->next;
  2502.             }
  2503.             show_curl_line( win );
  2504.          }
  2505.       } else if (diff < 0) {
  2506.          update_line( win );
  2507.          win->cline += diff;
  2508.          win->rline += diff;
  2509.          for (; diff < 0; diff++) {
  2510.             win->ll = win->ll->prev;
  2511.             win->bin_offset -= win->ll->len;
  2512.          }
  2513.          show_curl_line( win );
  2514.       }
  2515.    } else {
  2516.       if (diff > 0) {
  2517.          win->cline += diff;
  2518.          if ((long)(win->cline+1 - (win->top_line + win->ruler)) > win->rline)
  2519.             win->cline = (win->top_line + win->ruler) - 1 + (int)win->rline;
  2520.          file->dirty = LOCAL;
  2521.       } else if (diff < 0) {
  2522.          win->cline = win->cline + diff;
  2523.          file->dirty = LOCAL;
  2524.       }
  2525.    }
  2526.    if (g_status.command == CenterWindow  ||  g_status.command == CenterLine)
  2527.       cursor_sync( win );
  2528.    return( OK );
  2529. }
  2530.  
  2531.  
  2532. /*
  2533.  * Name:    horizontal_screen_right
  2534.  * Purpose: To move the cursor one screen to the right
  2535.  * Date:    September 13, 1991
  2536.  * Passed:  window:  pointer to current window
  2537.  * Notes:   Add 80 columns to the real cursor.  If the cursor is past the
  2538.  *          maximum line length then move it back.
  2539.  */
  2540. int  horizontal_screen_right( TDE_WIN *window )
  2541. {
  2542. int  col;
  2543.  
  2544.    col = window->rcol;
  2545.    col += (window->end_col + 1 - window->start_col);
  2546.    if (col < MAX_LINE_LENGTH) {
  2547.       window->rcol = col;
  2548.       window->bcol += (window->end_col + 1 - window->start_col);
  2549.       window->file_info->dirty = LOCAL;
  2550.       check_virtual_col( window, window->rcol, window->ccol );
  2551.       make_ruler( window );
  2552.       show_ruler( window );
  2553.    }
  2554.    cursor_sync( window );
  2555.    return( OK );
  2556. }
  2557.  
  2558.  
  2559. /*
  2560.  * Name:    horizontal_screen_left
  2561.  * Purpose: To move the cursor one screen to the left
  2562.  * Date:    September 13, 1991
  2563.  * Passed:  window:  pointer to current window
  2564.  * Notes:   Subtract screen width from the real cursor.  If the cursor is less
  2565.  *           than zero then see if bcol is zero.  If bcol is not zero then make
  2566.  *           bcol zero.
  2567.  */
  2568. int  horizontal_screen_left( TDE_WIN *window )
  2569. {
  2570. int  screen_width;
  2571.  
  2572.    screen_width = window->end_col + 1 - window->start_col;
  2573.    if (window->rcol - screen_width < 0) {
  2574.       if (window->bcol != 0) {
  2575.          window->bcol = 0;
  2576.          window->file_info->dirty = LOCAL;
  2577.       }
  2578.    } else {
  2579.       window->rcol -= screen_width;
  2580.       window->bcol -= screen_width;
  2581.       if (window->bcol < 0)
  2582.          window->bcol = 0;
  2583.       window->file_info->dirty = LOCAL;
  2584.    }
  2585.    check_virtual_col( window, window->rcol, window->ccol );
  2586.    cursor_sync( window );
  2587.    make_ruler( window );
  2588.    show_ruler( window );
  2589.    return( OK );
  2590. }
  2591.  
  2592.  
  2593. /*
  2594.  * Name:    goto_top_file
  2595.  * Purpose: To move the cursor to the top of the file.
  2596.  * Date:    June 5, 1991
  2597.  * Passed:  window:  pointer to current window
  2598.  */
  2599. int  goto_top_file( TDE_WIN *window )
  2600. {
  2601. register TDE_WIN *win;   /* put window pointer in a register */
  2602. long num;
  2603.  
  2604.    win = window;
  2605.    entab_linebuff( );
  2606.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2607.       return( ERROR );
  2608.    if (win->rline != win->cline - (win->top_line+win->ruler-1)) {
  2609.       win->bin_offset = 0;
  2610.       win->rline = win->cline - (win->top_line+win->ruler-1);
  2611.       win->ll = win->file_info->line_list;
  2612.       for (num=1; num < win->rline; num++) {
  2613.          win->bin_offset += win->ll->len;
  2614.          win->ll = win->ll->next;
  2615.       }
  2616.       display_current_window( win );
  2617.    }
  2618.    cursor_sync( win );
  2619.    return( OK );
  2620. }
  2621.  
  2622.  
  2623. /*
  2624.  * Name:    goto_end_file
  2625.  * Purpose: To move the cursor to the end of the file.
  2626.  * Date:    June 5, 1991
  2627.  * Passed:  window:  pointer to current window
  2628.  */
  2629. int  goto_end_file( TDE_WIN *window )
  2630. {
  2631. register TDE_WIN *win;  /* put window pointer in a register */
  2632. line_list_ptr ll;
  2633. long length;
  2634.  
  2635.    win = window;
  2636.    entab_linebuff( );
  2637.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2638.       return( ERROR );
  2639.    length = win->file_info->length;
  2640.    if (length > win->rline + win->bottom_line - win->cline) {
  2641.       win->rline = length - (win->bottom_line - win->cline) + 1;
  2642.       win->ll = win->file_info->line_list_end;
  2643.       for (;length >= win->rline; length--)
  2644.          win->ll = win->ll->prev;
  2645.  
  2646.       win->bin_offset = 0;
  2647.       ll = win->file_info->line_list;
  2648.       for (length = 1; length < win->rline; length++) {
  2649.          win->bin_offset += ll->len;
  2650.          ll = ll->next;
  2651.       }
  2652.  
  2653.       display_current_window( win );
  2654.    }
  2655.    cursor_sync( win );
  2656.    return( OK );
  2657. }
  2658.  
  2659.  
  2660. /*
  2661.  * Name:     goto_line
  2662.  * Purpose:  To move the cursor to a particular line in the file
  2663.  * Date:     June 5, 1991
  2664.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  2665.  * Passed:   window:  pointer to current window
  2666.  */
  2667. int  goto_line( TDE_WIN *window )
  2668. {
  2669. long number;            /* line number selected */
  2670. long n;
  2671. register TDE_WIN *win;   /* put window pointer in a register */
  2672. line_list_ptr ll;
  2673. int  rc;
  2674. char answer[MAX_COLS+2];
  2675. char temp[MAX_COLS+2];
  2676.  
  2677.    win = window;
  2678.    entab_linebuff( );
  2679.    if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2680.       return( ERROR );
  2681.    /*
  2682.     * find out where we are going
  2683.     */
  2684.  
  2685.    answer[0] = '\0';
  2686.    /*
  2687.     * line number:
  2688.     */
  2689.    if (get_name( find11, win->bottom_line, answer,
  2690.                  g_display.message_color ) != OK  ||  *answer == '\0')
  2691.       return( ERROR );
  2692.    number = atol( answer );
  2693.  
  2694.    if (number > 0  && number <= (long)win->file_info->length) {
  2695.       update_line( win );
  2696.       ll = win->ll;
  2697.       n = win->rline;
  2698.       if (number < win->rline) {
  2699.          if (n - number < number - 1) {
  2700.             for (; n > number; n--) {
  2701.                ll = ll->prev;
  2702.                win->bin_offset -= ll->len;
  2703.             }
  2704.          } else {
  2705.             ll = win->file_info->line_list;
  2706.             n = 1;
  2707.             for (; n < number; n++) {
  2708.                win->bin_offset += ll->len;
  2709.                ll = ll->next;
  2710.             }
  2711.          }
  2712.       } else if (number > win->rline) {
  2713.          for (; n < number; n++) {
  2714.             win->bin_offset += ll->len;
  2715.             ll = ll->next;
  2716.          }
  2717.       }
  2718.       find_adjust( win, ll, number, win->rcol );
  2719.       if (!win->file_info->dirty)
  2720.          show_curl_line( win );
  2721.       rc = OK;
  2722.    } else {
  2723.       /*
  2724.        * out of range.  must be in the range 1 -
  2725.        */
  2726.       strcpy( temp, find12 );
  2727.       my_ltoa( win->file_info->length, temp + strlen( temp ), 10 );
  2728.       error( WARNING, win->bottom_line, temp );
  2729.       rc = ERROR;
  2730.    }
  2731.    return( rc );
  2732. }
  2733.  
  2734.  
  2735. /*
  2736.  * Name:    set_marker
  2737.  * Purpose: To set file marker
  2738.  * Date:    December 28, 1991
  2739.  * Passed:  window:  pointer to current window
  2740.  */
  2741. int  set_marker( TDE_WIN *window )
  2742. {
  2743. register MARKER  *marker;       /* put the marker in a register */
  2744.  
  2745.    marker = &window->file_info->marker[g_status.command - SetMark1];
  2746.    marker->rline  = window->rline;
  2747.    marker->rcol   = window->rcol;
  2748.    marker->ccol   = window->ccol;
  2749.    marker->bcol   = window->bcol;
  2750.    marker->marked = TRUE;
  2751.    return( OK );
  2752. }
  2753.  
  2754.  
  2755. /*
  2756.  * Name:     goto_marker
  2757.  * Purpose:  To goto a file marker
  2758.  * Date:     December 28, 1991
  2759.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  2760.  * Passed:   window:  pointer to current window
  2761.  */
  2762. int  goto_marker( TDE_WIN *window )
  2763. {
  2764. int  m;
  2765. file_infos *file;
  2766. long new_rline;
  2767. long n;
  2768. MARKER *marker;
  2769. register TDE_WIN *win;   /* put window pointer in a register */
  2770. line_list_ptr ll;
  2771. int  rc;
  2772.  
  2773.    win = window;
  2774.    m = g_status.command - GotoMark1;
  2775.    file = win->file_info;
  2776.    marker = &file->marker[m];
  2777.    if (marker->marked) {
  2778.       entab_linebuff( );
  2779.       if (un_copy_line( win->ll, win, TRUE ) == ERROR)
  2780.          return( ERROR );
  2781.       file->dirty = LOCAL;
  2782.       if (marker->rline > file->length)
  2783.          marker->rline = file->length;
  2784.       if (marker->rline < 1l)
  2785.          marker->rline = 1l;
  2786.       new_rline = marker->rline;
  2787.       ll = win->ll;
  2788.       if (new_rline < win->rline) {
  2789.          if (win->rline - new_rline < new_rline - 1) {
  2790.             for (n=win->rline; n > new_rline; n--) {
  2791.                ll = ll->prev;
  2792.                win->bin_offset -= ll->len;
  2793.             }
  2794.          } else {
  2795.             ll = win->file_info->line_list;
  2796.             win->bin_offset = 0;
  2797.             n = 1;
  2798.             for (; n < new_rline; n++) {
  2799.                win->bin_offset += ll->len;
  2800.                ll = ll->next;
  2801.             }
  2802.          }
  2803.       } else if (new_rline > win->rline) {
  2804.          n = win->rline;
  2805.          for (; n < new_rline; n++) {
  2806.             win->bin_offset += ll->len;
  2807.             ll = ll->next;
  2808.          }
  2809.       }
  2810.       win->rline  = new_rline;
  2811.       win->ll     = ll;
  2812.       win->rcol   = marker->rcol;
  2813.       win->ccol   = marker->ccol;
  2814.       win->bcol   = marker->bcol;
  2815.       if (win->rline < (win->cline - ((win->top_line + win->ruler) - 1)))
  2816.          win->cline = (int)win->rline + (win->top_line + win->ruler) - 1;
  2817.       check_virtual_col( win, win->rcol, win->ccol );
  2818.       make_ruler( window );
  2819.       show_ruler( window );
  2820.       rc = OK;
  2821.    } else {
  2822.       if (m == 9)
  2823.          m = -1;
  2824.       *(utils13 + UTILS13_NO_SLOT) = (char)('0' + m + 1);
  2825.       /*
  2826.        * marker not set
  2827.        */
  2828.       error( WARNING, win->bottom_line, utils13 );
  2829.       rc = ERROR;
  2830.    }
  2831.    return( rc );
  2832. }
  2833.  
  2834.  
  2835. /*
  2836.  * Name:     date_time_stamp
  2837.  * Purpose:  put system date and time into file at cursor position
  2838.  * Date:     June 5, 1992
  2839.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  2840.  * Passed:   window:  pointer to current window
  2841.  */
  2842. int  date_time_stamp( TDE_WIN *window )
  2843. {
  2844. char stuff[20];
  2845. register char *dt;
  2846. int  year, month, day;
  2847. int  hours, minutes;
  2848. int  one, two, three;
  2849. int  i;
  2850. int  pm;
  2851. char answer[MAX_COLS+2];
  2852.  
  2853.  
  2854.    get_date( &year, &month, &day, &i );
  2855.    get_time( &hours, &minutes, &i, &i );
  2856.    dt = answer;
  2857.  
  2858.    /*
  2859.     * mod year with 100 if needed.
  2860.     */
  2861.    switch (mode.date_style) {
  2862.       case MM_DD_YY  :
  2863.       case DD_MM_YY  :
  2864.       case YY_MM_DD  :
  2865.          year = year % 100;
  2866.    }
  2867.  
  2868.    switch (mode.date_style) {
  2869.       case DD_MM_YY   :
  2870.       case DD_MM_YYYY :
  2871.          one = day;
  2872.          two = month;
  2873.          three = year;
  2874.          break;
  2875.       case YY_MM_DD   :
  2876.       case YYYY_MM_DD :
  2877.          one = year;
  2878.          two = month;
  2879.          three = day;
  2880.          break;
  2881.       case MM_DD_YY   :
  2882.       case MM_DD_YYYY :
  2883.       default         :
  2884.          one = month;
  2885.          two = day;
  2886.          three = year;
  2887.          break;
  2888.    }
  2889.    strcpy( dt, my_ltoa( one, stuff, 10 ) );
  2890.    strcat( dt, "-" );
  2891.    strcat( dt, my_ltoa( two, stuff, 10 ) );
  2892.    strcat( dt, "-" );
  2893.    strcat( dt, my_ltoa( three, stuff, 10 ) );
  2894.  
  2895.    strcat( dt, "  " );
  2896.  
  2897.    pm = FALSE;
  2898.    if (mode.time_style == _12_HOUR) {
  2899.       if (hours >= 12 && hours < 24)
  2900.          pm = TRUE;
  2901.       if (hours < 1)
  2902.          hours = 12;
  2903.       else if (hours >= 13)
  2904.          hours -= 12;
  2905.    }
  2906.  
  2907.    if (hours < 1)
  2908.       strcat( dt, "0" );
  2909.    strcat( dt, my_ltoa( hours, stuff, 10 ) );
  2910.    strcat( dt, ":" );
  2911.    if (minutes < 10)
  2912.       strcat( dt, "0" );
  2913.    strcat( dt, my_ltoa( minutes, stuff, 10 ) );
  2914.    if (mode.time_style == _12_HOUR)
  2915.       strcat( dt, pm == FALSE ? time_am : time_pm );
  2916.    strcat( dt, "  " );
  2917.    return( add_chars( dt, window ) );
  2918. }
  2919.  
  2920.  
  2921. /*
  2922.  * Name:    add_chars
  2923.  * Purpose: insert string into file
  2924.  * Date:    June 5, 1992
  2925.  * Passed:  string:  string to add to file
  2926.  *          window:  pointer to current window
  2927.  */
  2928. int  add_chars( char *string, TDE_WIN *window )
  2929. {
  2930. int  rc = OK;
  2931.  
  2932.    while (*string) {
  2933.       g_status.key_pressed = *string;
  2934.       rc = insert_overwrite( window );
  2935.       ++string;
  2936.    }
  2937.    return( rc );
  2938. }
  2939.